package traffic;

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.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.DOMException;

/** 
 * class Configuration
 *
 * @author Fco. Javier Cordero Cadenas, Francisco Grimaldo
 */

public class Configuration {
	org.w3c.dom.Document document;
    //DocumentType doctype;
    protected DocumentBuilderFactory domFactory = null;
    protected DocumentBuilder domBuilder = null;
    protected TransformerFactory tranFactory = null;
    protected Transformer transformer = null;
    private ArrayList<Village> villageList;
	private int collectDay;
	private Float priceXLitreGas;
	private Float kgCO2XLitreGas;
	private Float lowerLevelLearningFactor;
	private Float higherLevelLearningFactor;
	private Float lowerLevelForgettingFactor;
	private Float higherLevelForgettingFactor;
	private Float roadLength;
	private Float roadSpeed;
	private Float roadFlow;
	private Float toll;
	
    /**
     * Create new Configuration with org.w3c.dom.Document.
     */
    public Configuration(String xmlFileName) {
		villageList = new ArrayList <Village>();
         document = null;
         try {
            domFactory = DocumentBuilderFactory.newInstance();
            domFactory.setValidating(true);
            domFactory.setNamespaceAware(false);
        }
        catch(FactoryConfigurationError exp)
        {
            System.err.println(exp.toString());
        }
        try {
            domBuilder = domFactory.newDocumentBuilder();
        }
        catch(ParserConfigurationException exp)
        {
            System.err.println(exp.toString());
        }
        tranFactory = TransformerFactory.newInstance();
        try {
            transformer = tranFactory.newTransformer();
        }
        catch(TransformerConfigurationException exp) {
            System.err.println(exp.toString());
        }
		
        loadDOM(xmlFileName);
    }
	
	public int getCollectDay(){
		return collectDay;
	}
	
	public Float getPriceXLitreGas(){
		return priceXLitreGas;
	}
	
	public Float getKgCO2XLitreGas(){
		return kgCO2XLitreGas;
	}
	
	public Float getLowerLevelLearningFactor(){
		return lowerLevelLearningFactor;
	}
	
	public Float getHigherLevelLearningFactor(){
		return higherLevelLearningFactor;
	}
	
	public Float getLowerLevelForgettingFactor(){
		return lowerLevelForgettingFactor;
	}
	
	public Float getHigherLevelForgettingFactor(){
		return higherLevelForgettingFactor;
	}
	
	public Float getRoadLength(){
		return roadLength;
	}
	
	public Float getRoadSpeed(){
		return roadSpeed;
	}
	
	public Float getRoadFlow(){
		return roadFlow;
	}
	
	public Float getToll(){
		return toll;	
	}
	
	public void setCollectDay(int c){
		collectDay = c;
	}
	
	public void setPriceXLitreGas(Float price){
		priceXLitreGas = price;
	}
	
	public void setKgCO2XLitreGas(Float kg){
		kgCO2XLitreGas = kg;
	}
	
	public void setLowerLevelLearningFactor(Float lowLearn){
		lowerLevelLearningFactor = lowLearn;
	}
	
	public void setHigherLevelLearningFactor(Float highLearn){
		higherLevelLearningFactor = highLearn;
	}
	
	public void setLowerLevelForgettingFactor(Float lowForget){
		lowerLevelForgettingFactor = lowForget;
	}
	
	public void setHigherLevelForgettingFactor(Float highForget){
		higherLevelForgettingFactor = highForget;
	}
	
	public void setRoadLength(Float length){
		roadLength = length;
	}
	
	public void setRoadSpeed(Float speed){
		roadSpeed = speed;
	}
	
	public void setRoadFlow(Float flow){
		roadFlow = flow;
	}
	
	public void setToll(Float t){
		toll = t;
	}
	
	public void addVillage(Village vil){
        villageList.add(vil);
    }
	
	public Village getVillage(int id){
        for(Village v: villageList){
            if ((v.getVillageId()) == id){
				return (v);
			}
        }
		return null;
	}
	
    public ArrayList<Village> getVillageList(){
        return villageList;
    }
	
    public void showVillageList(){
        for(Village v: villageList)
            v.show();
    }

    public void loadDOM(String xmlFileName){

        try {
            document = domBuilder.parse(xmlFileName);
            //doctype = document.getDoctype();
                       
        } catch(org.xml.sax.SAXException exp) {
            System.out.println("'" + xmlFileName + "' is NOT well-formed.\n" + exp.toString());
        } catch(IOException exp) {
            System.err.println("Error al manejar el fichero '" + xmlFileName + "'" + exp.toString());
        } catch(Exception exp) {
            System.err.println(exp.toString());
        }
        visitDocument();
    }

	public void saveDOM(String xmlFileName){       
        org.w3c.dom.Document document = domBuilder.newDocument();             
        try {
            
            Source src = new DOMSource(document);
            File xmlFile = new File(xmlFileName);
            StreamResult dest = new StreamResult(xmlFile);
           
            transformer.transform(src, dest);            
        }
        catch(TransformerException exp) {
            System.err.println("Error al transformar DOM en XML: " + xmlFileName + exp.toString());
        }
        catch(Exception exp) {
            System.err.println(exp.toString());
        }
    }
	
	public org.w3c.dom.Element toElement(org.w3c.dom.Document document) {
        org.w3c.dom.Element elementConfiguration=null;
        try {
				elementConfiguration=document.createElement("configuration");
				for (Village vil : villageList) {
					org.w3c.dom.Element elementConf = vil.to_Villagelement(document);
					elementConfiguration.appendChild(document.createTextNode("\n"));
					elementConfiguration.appendChild(elementConf);
				}
            elementConfiguration.appendChild(document.createTextNode("\n"));
            document.appendChild(elementConfiguration);

        } catch(DOMException exp) {
            System.err.println(exp.toString());
        } catch(Exception exp) {
            System.err.println(exp.toString());
        }
        return elementConfiguration;
    }
	
    /**
     * Scan through org.w3c.dom.Document document.
     */
    public void visitDocument() {
        org.w3c.dom.Element element = document.getDocumentElement();
        if ((element != null) && element.getTagName().equals("configuration")) {
            visitElement_configuration(element);
        }
        if ((element != null) && element.getTagName().equals("village")) {
            visitElement_village(element);
        }
		if ((element != null) && element.getTagName().equals("config")) {
            visitElement_config(element);
        }
		if ((element != null) && element.getTagName().equals("road")) {
			visitElement_road(element);	
		}
    }

    /**
     * Scan through org.w3c.dom.Element named raizconf.
     */
    void visitElement_configuration(org.w3c.dom.Element element) {
        org.w3c.dom.NodeList nodes = element.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            org.w3c.dom.Node node = nodes.item(i);
            switch (node.getNodeType()) {
                case org.w3c.dom.Node.CDATA_SECTION_NODE:
                    break;
                case org.w3c.dom.Node.ELEMENT_NODE:
                    org.w3c.dom.Element nodeElement = (org.w3c.dom.Element) node;
                    if (nodeElement.getTagName().equals("village")) {
                        visitElement_village(nodeElement);
                    }
					if (nodeElement.getTagName().equals("config")) {
                        visitElement_config(nodeElement);
                    }
					if (nodeElement.getTagName().equals("road")) {
						visitElement_road(nodeElement);	
					}
                    break;
                case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE:
                    break;
            }
        }
    }
	
    /**
     * Scan through org.w3c.dom.Element named village.
     */
    void visitElement_village(org.w3c.dom.Element element) {
		Village vil = new Village();
        org.w3c.dom.NamedNodeMap attrs = element.getAttributes();
        for (int i = 0; i < attrs.getLength(); i++) {
            org.w3c.dom.Attr attr = (org.w3c.dom.Attr) attrs.item(i);
            if (attr.getName().equals("id")) {
				vil.setVillageId(Integer.parseInt(attr.getValue()));
            }
            if (attr.getName().equals("name")) {
                vil.setVillageName(attr.getValue().toString());
            }
            if (attr.getName().equals("numHabsReal")) {
				vil.setVillageNumHabs(Integer.parseInt(attr.getValue()));
            }
            if (attr.getName().equals("scale")) {
                vil.setVillageScale(Integer.parseInt(attr.getValue()));
            }
            if (attr.getName().equals("enterRoadKm")) {
                vil.setEnterRoadKm(Float.parseFloat(attr.getValue()));
            }
            if (attr.getName().equals("posVillageX")) {
                vil.setVillagePosX(Integer.parseInt(attr.getValue()));
            }
			if (attr.getName().equals("posVillageY")) {
                vil.setVillagePosY(Integer.parseInt(attr.getValue()));
            }
			if (attr.getName().equals("villageWidth")) {
                vil.setVillageWidth(Integer.parseInt(attr.getValue()));
            }
			if (attr.getName().equals("villageHeight")) {
                vil.setVillageHeight(Integer.parseInt(attr.getValue()));
            }
			if (attr.getName().equals("percentLow")) {
                vil.setPercentLow(Integer.parseInt(attr.getValue()));
            }
			if (attr.getName().equals("percentMiddle")) {
                vil.setPercentMiddle(Integer.parseInt(attr.getValue()));
            }
			if (attr.getName().equals("percentHigh")) {
                vil.setPercentHigh(Integer.parseInt(attr.getValue()));
            }
			if (attr.getName().equals("salaryLow")) {
                vil.setSalaryLow(Integer.parseInt(attr.getValue()));
            }
			if (attr.getName().equals("salaryMiddle")) {
                vil.setSalaryMiddle(Integer.parseInt(attr.getValue()));
            }
			if (attr.getName().equals("salaryHigh")) {
                vil.setSalaryHigh(Integer.parseInt(attr.getValue()));
            }
			if (attr.getName().equals("hasBus")) {
                vil.setHasBus(Boolean.parseBoolean(attr.getValue()));
            }
			if (attr.getName().equals("hasTrain")) {
                vil.setHasTrain(Boolean.parseBoolean(attr.getValue()));
            }
        }
		villageList.add(vil);
        org.w3c.dom.NodeList nodes = element.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            org.w3c.dom.Node node = nodes.item(i);
            switch (node.getNodeType()) {
                case org.w3c.dom.Node.CDATA_SECTION_NODE:
                    break;
				case org.w3c.dom.Node.ELEMENT_NODE:
                    break;
                case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE:
                    break;
            }
        }
    }
	
	/**
     * Scan through org.w3c.dom.Element named config.
     */
    void visitElement_config(org.w3c.dom.Element element) {
		org.w3c.dom.NamedNodeMap attrs = element.getAttributes();
        for (int i = 0; i < attrs.getLength(); i++) {
            org.w3c.dom.Attr attr = (org.w3c.dom.Attr) attrs.item(i);
            if (attr.getName().equals("collectDay")) {
				this.setCollectDay(Integer.parseInt(attr.getValue()));
            }
			if (attr.getName().equals("priceXLitreGas")) {
				this.setPriceXLitreGas(Float.parseFloat(attr.getValue()));
            }
			if (attr.getName().equals("kgCO2XLitreGas")) {
				this.setKgCO2XLitreGas(Float.parseFloat(attr.getValue()));
            }
			if (attr.getName().equals("lowerLevelLearningFactor")) {
				this.setLowerLevelLearningFactor(Float.parseFloat(attr.getValue()));
            }
			if (attr.getName().equals("higherLevelLearningFactor")) {
				this.setHigherLevelLearningFactor(Float.parseFloat(attr.getValue()));
            }
			if (attr.getName().equals("lowerLevelForgettingFactor")) {
				this.setLowerLevelForgettingFactor(Float.parseFloat(attr.getValue()));
            }
			if (attr.getName().equals("higherLevelForgettingFactor")) {
				this.setHigherLevelForgettingFactor(Float.parseFloat(attr.getValue()));
            }
			if (attr.getName().equals("toll")) {
				this.setToll(Float.parseFloat(attr.getValue()));
            }
        }
	}
	
	/**
     * Scan through org.w3c.dom.Element named road.
     */
    void visitElement_road(org.w3c.dom.Element element) {
		org.w3c.dom.NamedNodeMap attrs = element.getAttributes();
        for (int i = 0; i < attrs.getLength(); i++) {
            org.w3c.dom.Attr attr = (org.w3c.dom.Attr) attrs.item(i);
            if (attr.getName().equals("length")) {
				this.setRoadLength(Float.parseFloat(attr.getValue()));
            }
			if (attr.getName().equals("speed")) {
				this.setRoadSpeed(Float.parseFloat(attr.getValue()));
            }
			if (attr.getName().equals("flow")) {
				this.setRoadFlow(Float.parseFloat(attr.getValue()));
            }
        }
	}
}