package org.spview.filehandler;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class FileParser {
	private ArrayList<Element> pathlist = new ArrayList<>();
	private ArrayList<String> attrlist = new ArrayList<>();
	private ArrayList<String> AttributeOfFilelist = new ArrayList<>();
	private ArrayList<String> yReverseElement = new ArrayList<>();
	private ArrayList<String> hideElement = new ArrayList<>();
	private ArrayList<String> xShiftState = new ArrayList<>();
	private ArrayList<String> yShiftState = new ArrayList<>();
	private String minX, maxX;
	private String minY, maxY;
	private String indexColorPred;
	private String indexColorExp;

	public FileParser(String filename) throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		File fileXML = new File(filename);
		Document xml = builder.parse(fileXML);
		Element spvFile = xml.getDocumentElement();

		getAttributeList(spvFile, this.AttributeOfFilelist, "File", "AttributeOfFile");
		getAttributePath(spvFile, this.pathlist, this.attrlist);
		getTagValueList(spvFile, this.yReverseElement, "yReverse");
		getTagValueList(spvFile, this.hideElement, "hide");

		this.indexColorPred = getTagValue(spvFile, "indexColorPred", "0");
		this.indexColorExp = getTagValue(spvFile, "indexColorExp", "0");

		getTagValueList(spvFile, this.xShiftState, "xShiftState");
		getTagValueList(spvFile, this.yShiftState, "yShiftState");

		this.minX = getTagValue(spvFile, "xmin", "0.0");
		this.maxX = getTagValue(spvFile, "xmax", "0.0");
		this.minY = getTagValue(spvFile, "ymin", "0.0");
		this.maxY = getTagValue(spvFile, "ymax", "0.0");
	}

	private static void getAttributeList(Node n, ArrayList<String> array, String string, String attribute) {
		if (n instanceof Element) {
			Element element = (Element) n;
			if (n.getNodeName().equals(string)) {
				array.add(element.getAttribute(attribute));
			}
			// The child nodes of the current node are handled.
			int nbChild = n.getChildNodes().getLength();
			// A list of these child nodes is retrieved
			NodeList list = n.getChildNodes();

			// The program checks into the list
			for (int i = 0; i < nbChild; i++) {
				Node n2 = list.item(i);
				// if the child node is an Element, it is handled
				if (n2 instanceof Element) {
					// Recursive use of the method to handle the node and its children
					getAttributeList(n2, array, string, attribute);
				}
			}
		}
	}

	private static void getTagValueList(Node n, ArrayList<String> array, String string) {
		if (n instanceof Element) {
			Element element = (Element) n;
			if (n.getNodeName().equals(string)) {
				array.add(element.getTextContent());
			}
			// The child nodes of the current node are handled.
			int nbChild = n.getChildNodes().getLength();
			// A list of these child nodes is retrieved
			NodeList list = n.getChildNodes();

			// The program checks into the list
			for (int i = 0; i < nbChild; i++) {
				Node n2 = list.item(i);
				// if the child node is an Element, it is handled
				if (n2 instanceof Element) {
					// Recursive use of the method to handle the node and its children
					getTagValueList(n2, array, string);
				}
			}
		}
	}

	private static String getTagValue(Element eElement, String sTag, String defaultVal) {
		if (eElement.getElementsByTagName(sTag).item(0) == null) {
			return defaultVal;
		}
		NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
		Node nValue = (Node) nlList.item(0);
		return nValue.getNodeValue();
	}

	private static void getAttributePath(Node n, ArrayList<Element> pathlist, ArrayList<String> attrlist) {
		String type = "";
		if (n instanceof Element) {
			Element element = (Element) n;
			if (n.getNodeName().equals("path")) {
				pathlist.add(element);
				type = element.getAttribute("Type");
				attrlist.add(type);
			}
			// The child nodes of the current node are handled.
			int nbChild = n.getChildNodes().getLength();
			// A list of these child nodes is retrieved
			NodeList list = n.getChildNodes();

			// The program checks into the list
			for (int i = 0; i < nbChild; i++) {
				Node n2 = list.item(i);
				// if the child node is an Element, it is handled
				if (n2 instanceof Element) {
					// Recursive use of the method to handle the node and its children
					getAttributePath(n2, pathlist, attrlist);
				}
			}
		}
	}

	/* getter and setter */

	public ArrayList<String> getAttributeOfFilelist() {
		return AttributeOfFilelist;
	}

	public ArrayList<Element> getPathlist() {
		return pathlist;
	}

	public ArrayList<String> getAttrlist() {
		return attrlist;
	}

	public ArrayList<String> getyReverseElementslist() {
		return yReverseElement;
	}

	public ArrayList<String> getHideElementslist() {
		return hideElement;
	}

	public ArrayList<String> getxShiftElementslist() {
		return xShiftState;
	}

	public ArrayList<String> getyShiftElementslist() {
		return yShiftState;
	}

	public double getMinX() {
		return Double.parseDouble(this.minX);
	}

	public double getMinY() {
		return Double.parseDouble(this.minY);
	}

	public double getMaxX() {
		return Double.parseDouble(this.maxX);
	}

	public double getMaxY() {
		return Double.parseDouble(this.maxY);
	}

	public int getIndexColorPred() {
		return Integer.parseInt(indexColorPred);
	}

	public int getIndexColorExp() {
		return Integer.parseInt(indexColorExp);
	}
}