package es.uv.saic.service;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import es.uv.saic.domain.Indicador;

@Service
public class IndicadorService {
	
	@Autowired
	private OrganService os;
	
	public IndicadorService() {}

	public List<Indicador> getFromTitulacion(Integer tit, Integer curs) throws ParserConfigurationException, MalformedURLException, IOException, SAXException {
	    DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
	    f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
	    f.setNamespaceAware(false);
	    f.setValidating(false);
	    DocumentBuilder build = f.newDocumentBuilder();
	    
	    List<Integer> tits = this.os.getEquivalents(tit, "T");
	    tits.add(tit);
	    //Collections.sort(tits).reverse(); 
	    	    
	    String periodo = Integer.toString(curs-1)+"-"+Integer.toString(curs);
	    String periodoAnt = Integer.toString(curs-2)+"-"+Integer.toString(curs-1);
	    List<Indicador> indicadores = new ArrayList<Indicador>();
	    boolean hasCurs = false;
	    int xtits = 0, xurls = 0;
	    List<String> urls = Arrays.asList(new String[]{"http://bancuv.uv.es/wwwuv/stuff/web/siga/SGIC", "http://bancuv.uv.es/wwwuv/stuff/web/siga/previo/SGIC"});
	    //List<String> urls = Arrays.asList(new String[]{"http://bancuv.uv.es/wwwuv/stuff/web/siga/SGIC"});
	    
	    while(!hasCurs && xtits < tits.size() && xurls < urls.size()) {
	    	String url = urls.get(xurls)+tits.get(xtits)+".xml";
	    	String resText = "";
	    	try {
	    		URLConnection urlConnection = new URL(url).openConnection();
	    		urlConnection.addRequestProperty("Accept", "application/xml");
	    		InputStream res = urlConnection.getInputStream();
	    		resText = new String(res.readAllBytes(), StandardCharsets.UTF_8);
	    	}
	    	catch(Exception e){
	    		resText = "";
	    	}

		    if(!resText.contains("curso=\""+periodo+"\"")) {  // not contains data from selected year
		    	xtits+=1;
		    	if(xtits > tits.size()-1 && xurls < urls.size()-1) {
		    		xtits=0;
		    		xurls+=1;
		    	}
		    }
		    else {
		    	hasCurs = true;
		    	indicadores = this.extract(build, periodo, periodoAnt, resText);
		    }
	    }	
	    return indicadores;
	}
	
	private List<Indicador> extract(DocumentBuilder build, String periodo, String periodoAnt, String resText) throws SAXException, IOException {
    	Document doc = build.parse(new InputSource(new StringReader(resText)));
	    doc.getDocumentElement().normalize();
	    NodeList nodedim = doc.getElementsByTagName("Dimension");
	    List<Indicador> indicadores = new ArrayList<Indicador>();
    
	    for(int i = 0; i < nodedim.getLength(); i++) { // each dim
	    	Element a = (Element)nodedim.item(i);
	    	NodeList nodeind = a.getElementsByTagName("indicador");
	    	for(int j = 0; j < nodeind.getLength(); j++) { // each ind
	    		Element b = (Element)nodeind.item(j);
	    		NodeList nodesub = b.getElementsByTagName("subindicador");
	    		if(nodesub.getLength() > 0) { // has subind
	    			for(int k = 0; k < nodesub.getLength(); k++) { // each subind
	    				Element c = (Element)nodesub.item(k);
	    				NodeList nodevals = c.getElementsByTagName("cursoAcademico");
	    				Indicador ind = new Indicador(a.getAttribute("codigo"), c.getAttribute("codigo"), "");
				    	for(int z = 0; z < nodevals.getLength(); z++) { // each val
				    		Element d = (Element)nodevals.item(z);
				    		if(d.getAttribute("curso").equals(periodo)) {
				    			ind.setValor(d.getAttribute("valor"));
				    		}
				    		else if((c.getAttribute("codigo").equals("I_DE7_04") || (c.getAttribute("codigo").equals("I_DE7_06"))) && d.getAttribute("curso").equals(periodoAnt)) {
				    			ind.setValor(d.getAttribute("valor"));
				    		}
				    	}
				    	indicadores.add(ind);
	    			}
	    		}
	    		else { // not has subind
			    	NodeList nodevals = b.getElementsByTagName("cursoAcademico");
			    	Indicador ind = new Indicador(a.getAttribute("codigo"), b.getAttribute("codigo"), "");
			    	for(int k = 0; k < nodevals.getLength(); k++) { // each val
			    		Element c = (Element)nodevals.item(k);
			    		if(c.getAttribute("curso").equals(periodo)) {
			    			ind.setValor(c.getAttribute("valor"));
			    		}
			    		else if((b.getAttribute("codigo").equals("I_DE7_04") || (b.getAttribute("codigo").equals("I_DE7_06"))) && c.getAttribute("curso").equals(periodoAnt)) {
			    			ind.setValor(c.getAttribute("valor"));
			    		}
			    	}
			    	indicadores.add(ind);
	    		}	
	    	}
	    }
		return indicadores;
	}
	
	public List<Indicador> getGraphData(Integer tit) throws ParserConfigurationException{
		DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
	    f.setNamespaceAware(false);
	    f.setValidating(false);
	    DocumentBuilder build = f.newDocumentBuilder();
	    
	    List<Indicador> inds = new ArrayList<Indicador>();
	    List<Integer> tits = this.os.getEquivalents(tit, "T");
	    if(tits.size() > 0) {
	    	tit = tits.get(tits.size()-1);
	    }
	    
	    String url = "http://bancuv.uv.es/wwwuv/stuff/web/siga/SGIC"+tit.toString()+".xml";
	    String fileText;
	    try {
    		URLConnection urlConnection = new URL(url).openConnection();
    		urlConnection.addRequestProperty("Accept", "application/xml");
    		InputStream res = urlConnection.getInputStream();
    		fileText = new String(res.readAllBytes(), StandardCharsets.UTF_8);
    		inds = this.extractAll(build, fileText);
    	}
    	catch(Exception e){
    		fileText = "";
    		return null;
    	}
	    
	    return inds;
	}
	
	private List<Indicador> extractAll(DocumentBuilder build, String fileText) throws SAXException, IOException {
    	Document doc = build.parse(new InputSource(new StringReader(fileText)));
	    doc.getDocumentElement().normalize();
	    NodeList nodedim = doc.getElementsByTagName("Dimension");
	    List<Indicador> indicadores = new ArrayList<Indicador>();
    
	    for(int i = 0; i < nodedim.getLength(); i++) { // each dim
	    	Element a = (Element)nodedim.item(i);
	    	NodeList nodeind = a.getElementsByTagName("indicador");
	    	for(int j = 0; j < nodeind.getLength(); j++) { // each ind
	    		Element b = (Element)nodeind.item(j);
	    		NodeList nodesub = b.getElementsByTagName("subindicador");
	    		if(nodesub.getLength() > 0) { // has subind
	    			for(int k = 0; k < nodesub.getLength(); k++) { // each subind
	    				Element c = (Element)nodesub.item(k);
	    				NodeList nodevals = c.getElementsByTagName("cursoAcademico");
	    				Indicador ind = new Indicador(a.getAttribute("codigo"), c.getAttribute("codigo"), "");
				    	for(int z = 0; z < nodevals.getLength(); z++) { // each val
				    		Element d = (Element)nodevals.item(z);
				    		ind.addCursoValor(d.getAttribute("curso"), d.getAttribute("valor").replace("%",""));
				    		//ind.setValor();
				    	}
				    	indicadores.add(ind);
	    			}
	    		}
	    		else { // not has subind
			    	NodeList nodevals = b.getElementsByTagName("cursoAcademico");
			    	Indicador ind = new Indicador(a.getAttribute("codigo"), b.getAttribute("codigo"), "");
			    	for(int k = 0; k < nodevals.getLength(); k++) { // each val
			    		Element c = (Element)nodevals.item(k);
			    		ind.addCursoValor(c.getAttribute("curso"), c.getAttribute("valor").replace("%",""));
			    	}
			    	indicadores.add(ind);
	    		}	
	    	}
	    }
		return indicadores;
	}
	
}
