/*
 * Created on Jul 24, 2008 (C) Copyright TANDBERG Television Ltd.
 */

package com.tandbergtv.watchpoint.pmm.title.provider.xport;

import static javax.xml.xpath.XPathConstants.NODESET;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.tandbergtv.watchpoint.pmm.title.provider.TitleProviderInstance;

/**
 * Responsible for parsing the file containing the title provider instance configuration
 * 
 * @author Vijay Silva
 */
class TitleProviderInstanceParser {

	/* The XPath expression for the Title Provider Instance Nodes */
	private static final String INSTANCE_XPATH = "//TitleProviderInstance";

	/* The Attribute of the title provider instance element for the display name */
	private static final String INSTANCE_NAME_ATTR = "name";

	/* The Attribute of the title provider instance element for the key */
	private static final String INSTANCE_KEY_ATTR = "key";

	/* The Attribute of the title provider instance property element */
	private static final String PROPERTY_ELEMENT = "Property";

	/* The Attribute of the title provider instance property element for the key */
	private static final String PROPERTY_KEY_ATTR = "key";

	/**
	 * Constructor
	 */
	public TitleProviderInstanceParser() {
	}

	/**
	 * Parse the XML Document that can be read from the provided input stream and get the list of
	 * provider instances from the document.
	 * 
	 * @param stream The Input Stream from which to read the instance configuration file
	 * @return the list of Title Provider Instances
	 * @throws InstanceConfigurationException
	 */
	public List<TitleProviderInstance> parse(InputStream stream)
			throws InstanceConfigurationException {
		List<TitleProviderInstance> instances = new ArrayList<TitleProviderInstance>();

		Document document = null;
		try {
			DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			document = builder.parse(stream);
		} catch (Exception e) {
			String msg = "Failed to load the Instance Configuration XML file from stream.";
			throw new InstanceConfigurationException(msg, e);
		}

		XPath xpath = XPathFactory.newInstance().newXPath();
		NodeList nodes = null;
		try {
			nodes = (NodeList) xpath.evaluate(INSTANCE_XPATH, document, NODESET);
		} catch (Exception e) {
			String msg = "Failed to get list of TitleProviderInstance elements "
					+ "from the Title Provider Instance configuration XML file.";
			throw new InstanceConfigurationException(msg, e);
		}

		int nodeCount = (nodes != null) ? nodes.getLength() : 0;
		for (int i = 0; i < nodeCount; i++) {
			Element instanceElement = (Element) nodes.item(i);
			instances.add(this.parseTitleProviderInstance(instanceElement, xpath));
		}

		return instances;
	}

	/* Parse the Title Provider Instance Element and build the object */
	private TitleProviderInstance parseTitleProviderInstance(Element element, XPath xpath) {
		TitleProviderInstance instance = new TitleProviderInstance();

		instance.setKey(element.getAttribute(INSTANCE_KEY_ATTR));
		instance.setName(element.getAttribute(INSTANCE_NAME_ATTR));

		Map<String, String> properties = instance.getProperties();
		NodeList nodes = element.getElementsByTagName(PROPERTY_ELEMENT);
		int nodeCount = (nodes != null) ? nodes.getLength() : 0;
		for (int i = 0; i < nodeCount; i++) {
			Element propertyElement = (Element) nodes.item(i);
			String key = propertyElement.getAttribute(PROPERTY_KEY_ATTR);
			String value = propertyElement.getTextContent();
			properties.put(key, value);
		}

		return instance;
	}
}
