package com.tandbergtv.metadatamanager.util;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

/**
 * Class that reads the map of fields to TTV Xpath Note: This approach for
 * resolving field to xpaths is only for version 1.0.
 * 
 * @author spuranik
 * 
 */
public class MappingFileParser {
	private static String MAPPING_DELIMITER = ",";

	/**
	 * Reads the mapping file which contains the field and its TTV xpaths and
	 * saves it in a local map. The format of the mapping file is: field name,
	 * TTV xpath
	 * 
	 * @return
	 */
	public static Map<String, String> readFieldMapping(String mappingResource) {
		Map<String, String> mappings = new HashMap<String, String>();
		BufferedReader br = new BufferedReader(new InputStreamReader(
				MappingFileParser.class.getClassLoader().getResourceAsStream(
						mappingResource)));
		readInputStream(mappings, br);
		return mappings;
	}

	/**
	 * 
	 * @param mappingResourceStream
	 * @return
	 */
	public static Map<String, String> readFieldMapping(
			InputStream mappingResourceStream) {
		Map<String, String> mappings = new HashMap<String, String>();
		BufferedReader br = new BufferedReader(new InputStreamReader(
				mappingResourceStream));
		readInputStream(mappings, br);
		return mappings;
	}

	/**
	 * 
	 * @param mappingResourceStream
	 * @return
	 */
	public static Map<String, Boolean> readFieldMappingWithBooleanValue(
			InputStream mappingResourceStream) {
		Map<String, Boolean> mappings = new HashMap<String, Boolean>();
		BufferedReader br = new BufferedReader(new InputStreamReader(
				mappingResourceStream));
		readInputStreamWithBooleanValue(mappings, br);
		return mappings;
	}

	/**
	 * 
	 * @param mappingResourceUrl
	 * @return
	 */
	public static Map<String, String> readFieldMapping(URL mappingResourceUrl) {
		Map<String, String> mappings = new HashMap<String, String>();
		BufferedReader br = null;
		try {
			URLConnection conn = mappingResourceUrl.openConnection();
			br = new BufferedReader(
					new InputStreamReader(conn.getInputStream()));
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		readInputStream(mappings, br);
		return mappings;
	}

	/**
	 * 
	 * @param mappingResourceFile
	 * @return
	 */
	public static Map<String, String> readFieldMapping(
			java.io.File mappingResourceFile) {
		Map<String, String> mappings = new HashMap<String, String>();
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(
					mappingResourceFile)));
		} catch (FileNotFoundException e) {
			throw new RuntimeException(e);
		}
		readInputStream(mappings, br);
		return mappings;
	}

	/**
	 * @param mappings
	 * @param br
	 * @throws RuntimeException
	 */
	private static void readInputStream(Map<String, String> mappings,
			BufferedReader br) throws RuntimeException {
		String line;
		// Read File Line By Line
		try {
			while ((line = br.readLine()) != null) {
				String[] fieldMapping = line.split(MAPPING_DELIMITER);
				mappings.put(fieldMapping[0].trim(), fieldMapping[1].trim());
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @param mappings
	 * @param br
	 * @throws RuntimeException
	 */
	private static void readInputStreamWithBooleanValue(Map<String, Boolean> mappings,
			BufferedReader br) throws RuntimeException {
		String line;
		// Read File Line By Line
		try {
			while ((line = br.readLine()) != null) {
				String[] fieldMapping = line.split(MAPPING_DELIMITER);
				mappings.put(fieldMapping[0].trim(), Boolean.valueOf(fieldMapping[1].trim()));
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Util method to retrieve the ttv xpath for the given field. If not found
	 * returns an empty string.
	 * 
	 * @param field
	 * @return
	 */
	public static String getMapping(String mappingResource, String field) {
		Map<String, String> fields = readFieldMapping(mappingResource);
		return fields.containsKey(field) ? fields.get(field) : "";
	}

	/**
	 * 
	 * @param mappingResourceUrl
	 * @param field
	 * @return
	 */
	public static String getMapping(URL mappingResourceUrl, String field) {
		Map<String, String> fields = readFieldMapping(mappingResourceUrl);
		return fields.containsKey(field) ? fields.get(field) : "";
	}

}
