/*
 * Created on Apr 16, 2008 (C) Copyright TANDBERG Television Ltd.
 */

package com.tandbergtv.watchpoint.pmm.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * Utility Class to convert network paths between the UNC path and the Unix style path
 * 
 * @author Vijay Silva
 */
public final class PathConverter {

	/* The UNC/Windows Path Separator Regular Expression Pattern */
	private static final String UNC_PATH_SEPARATOR_PATTERN = "\\\\";

	/* The UNIX Path Separator Regular Expression Pattern */
	private static final String UNIX_PATH_SEPARATOR_PATTERN = "/";

	/* The Singleton instance */
	private static PathConverter INSTANCE = null;

	private Map<String, String> uncPathMap = new HashMap<String, String>();

	private Map<String, String> mountMap = new HashMap<String, String>();

	/* The Resource Path */
	private static final String RESOURCE_PATH = "/template-actions/pathConversion.properties";

	/* Cannot Instantiate */
	private PathConverter() {
		this.loadPathConfiguration();
	}

	/* Loads the Path Configuration */
	private synchronized void loadPathConfiguration() {
		this.mountMap.clear();
		this.uncPathMap.clear();

		try {
			InputStream stream = this.getClass().getResourceAsStream(RESOURCE_PATH);
			Properties config = new Properties();
			config.load(stream);

			for (Object keyObject : config.keySet()) {
				String mountPath = ((String) keyObject).trim();
				String uncPath = config.getProperty(mountPath).trim();

				this.mountMap.put(mountPath, uncPath);
				this.uncPathMap.put(uncPath, mountPath);
			}
		} catch (IOException e) {
			String msg = "Failed to load the Path configuration file: " + RESOURCE_PATH;
			throw new RuntimeException(msg, e);
		}
	}

	/* load the paths */
	public static synchronized PathConverter getInstance() {
		if (INSTANCE == null) {
			INSTANCE = new PathConverter();
		}

		return INSTANCE;
	}

	/**
	 * Converts a UNC style Path to the Unix style Path
	 * 
	 * @param uncPath
	 *            The UNC Path
	 * @return The equivalent Unix path
	 */
	public String convertUNCToUnix(String uncPath) {
		if (uncPath == null)
			return null;

		String unixPath = this.replacePath(uncPath, true);
		return unixPath.replaceAll(UNC_PATH_SEPARATOR_PATTERN, UNIX_PATH_SEPARATOR_PATTERN);
	}

	/**
	 * Converts a Unix style Path to the UNC style Path
	 * 
	 * @param unixPath
	 *            The Unix Path
	 * @return The equivalent UNC path
	 */
	public String convertUnixToUNC(String unixPath) {
		if (unixPath == null)
			return null;

		String uncPath = this.replacePath(unixPath, false);
		return uncPath.replaceAll(UNIX_PATH_SEPARATOR_PATTERN, UNC_PATH_SEPARATOR_PATTERN);
	}

	/* Replace the UNC Path with the Mount Path or vice versa */
	private String replacePath(String path, boolean isUNCPath) {
		String convertedPath = path.trim();

		Map<String, String> pathMap = (isUNCPath) ? this.uncPathMap : this.mountMap;
		for (String mappedPath : pathMap.keySet()) {
			if (path.startsWith(mappedPath)) {
				convertedPath = pathMap.get(mappedPath) + path.substring(mappedPath.length());
				break;
			}
		}

		return convertedPath;
	}
}
