package donnee;

import com.github.benmanes.caffeine.cache.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.io.ByteArrayInputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import controleur.Journal;
import modele.EnsembleDeDonnees;

import java.time.LocalDate;
import java.time.YearMonth;
import java.time.Year;



public class AppuiDeBoutonDAO {
	protected static final String URL_LISTE_APPUI_DE_BOUTON_PAR_ANNEE = "http://172.105.23.70/service.telecommande/annee/%d";
	protected static final String URL_LISTE_APPUI_DE_BOUTON_PAR_MOIS = "http://172.105.23.70/service.telecommande/mois/%d/%d";
	protected static final String URL_LISTE_APPUI_DE_BOUTON_PAR_JOUR = "http://172.105.23.70/service.telecommande/jour/%d/%d/%d";
	protected static final String TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJmdW5ueS11cmwubG9sIiwiaWF0IjoxNzc0NDc1MDkwLCJleHAiOjE3NzcxNTM0OTAsIm5iZiI6NTAwfQ.2MqfE5iFQskS4CiuuBJo2eP9CV_yMOfp7uioMs3YxPw";

	Cache<String, EnsembleDeDonnees> cache = Caffeine.newBuilder()
			.maximumSize(1000)
			.expireAfterWrite(24, TimeUnit.HOURS)
			.build();
	
	public EnsembleDeDonnees listerAppuisDeBoutonParAnnee(Year anneeALister){
		Journal.ecrire(Journal.NIVEAU.ROULEMENT, "AppuiDeBoutonDAO.listerAppuisDeBoutonParAnnee() : " + anneeALister);
		
		//EnsembleDeDonnees ensembleDeDonnees = cache.getIfPresent("appuisDeBoutonParAnnee");
		
		//if (ensembleDeDonnees == null) {
			String url = String.format(URL_LISTE_APPUI_DE_BOUTON_PAR_ANNEE, anneeALister.getValue());
			String xml = recupererXml(url);
			EnsembleDeDonnees ensembleDeDonnees = extraireStatistiques(xml);
			ensembleDeDonnees.setDonnees(extraireDonneesDesMois(xml));
			
			//cache.put("appuisDeBoutonParAnnee", ensembleDeDonnees);
		//}
		
		return ensembleDeDonnees;
	}
	
	public EnsembleDeDonnees listerAppuisDeBoutonParMois(YearMonth moisALister){
		Journal.ecrire(Journal.NIVEAU.ROULEMENT, "AppuiDeBoutonDAO.listerAppuisDeBoutonParMois() : " + moisALister);
		
		//EnsembleDeDonnees ensembleDeDonnees = cache.getIfPresent("appuisDeBoutonParMois");
		
		//if (ensembleDeDonnees == null) {
			String url = String.format(URL_LISTE_APPUI_DE_BOUTON_PAR_MOIS, moisALister.getYear(), moisALister.getMonthValue());
			String xml = recupererXml(url);
			EnsembleDeDonnees ensembleDeDonnees = extraireStatistiques(xml);
			ensembleDeDonnees.setDonnees(extraireDonneesDesJours(xml));
			
			//cache.put("appuisDeBoutonParMois", ensembleDeDonnees);
		//}
		
		return ensembleDeDonnees;
	}
	
	public EnsembleDeDonnees listerAppuisDeBoutonParJour(LocalDate dateALister){
		Journal.ecrire(Journal.NIVEAU.ROULEMENT, "AppuiDeBoutonDAO.listerAppuisDeBoutonParJour() : " + dateALister);
		
		//EnsembleDeDonnees ensembleDeDonnees = cache.getIfPresent("appuisDeBoutonParJour");
		
		//if (ensembleDeDonnees == null) {
			String url = String.format(URL_LISTE_APPUI_DE_BOUTON_PAR_JOUR, dateALister.getYear(), dateALister.getMonthValue(), dateALister.getDayOfMonth());
			String xml = recupererXml(url);
			EnsembleDeDonnees ensembleDeDonnees = extraireStatistiques(xml);
			ensembleDeDonnees.setDonnees(extraireDonneesDesHeures(xml));
			
			//cache.put("appuisDeBoutonParJour", ensembleDeDonnees);
		//}
		
		return ensembleDeDonnees;
	}
	
	
	
	
	protected static String recupererXml(String url){
		System.out.println(url);
		Journal.ecrire(Journal.NIVEAU.ROULEMENT, "AppuiDeBoutonDAO.listerAppuisDeBoutonParUrl() : " + url);
		
		String xml = "";
		
		try {
			HttpClient client = HttpClient.newHttpClient();
			HttpRequest requete = HttpRequest.newBuilder()
					.uri(new URI(url))
					.setHeader("Authorization", "Bearer "+TOKEN)
					.GET()
					.build();
			HttpResponse<String> reponse = client.send(requete, BodyHandlers.ofString());
			System.out.println(reponse.body());
			xml = reponse.body();
		}catch (Exception e) {
			e.printStackTrace();
		}
		
		return xml;
	}
	
	
	protected static EnsembleDeDonnees extraireStatistiques(String xml) {
		Journal.ecrire(Journal.NIVEAU.ROULEMENT, "AppuiDeBoutonDAO.extraireStatistiques()");
		
		EnsembleDeDonnees ensembleDeDonnees = new EnsembleDeDonnees();
		
		try {
			DocumentBuilder parseur = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document document = parseur.parse(new ByteArrayInputStream(xml.getBytes()));
			NodeList noeudStatistiques = document.getElementsByTagName("statistiques");
			Element elementStatistiques = (Element) noeudStatistiques.item(0);
			
			String moyenneStr = recupererElementText(elementStatistiques, "moyenne");
			String minimumStr = recupererElementText(elementStatistiques, "minimum");
			String maximumStr = recupererElementText(elementStatistiques, "maximum");
			
			if(moyenneStr.isBlank()) moyenneStr = "0";
			if(minimumStr.isBlank()) minimumStr = "0";
			if(maximumStr.isBlank()) maximumStr = "0";
			
			float moyenne = Float.parseFloat(moyenneStr);
			float minimum = Float.parseFloat(minimumStr);
			float maximum = Float.parseFloat(maximumStr);
			
			ensembleDeDonnees.setMoyenne(moyenne);
			ensembleDeDonnees.setMinimum(minimum);
			ensembleDeDonnees.setMaximum(maximum);
		}catch(Exception e) {
			e.printStackTrace();
		}
		
		return ensembleDeDonnees;
	}
	
	
	protected static List<Float> extraireDonneesDesMois(String xml){
		Journal.ecrire(Journal.NIVEAU.ROULEMENT, "AppuiDeBoutonDAO.extraireDonneesDesMois()");
		
		List<Float> donnees = new ArrayList<Float>();
		
		try {
			DocumentBuilder parseur = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document document = parseur.parse(new ByteArrayInputStream(xml.getBytes()));
			NodeList noeudListMois = document.getElementsByTagName("moyenne_mois");
			Element elementListMois = (Element) noeudListMois.item(0);
			
			for (int i = 0 ; i < 12 ; i++) {
				String moyenneDuMoisStr = recupererElementText(elementListMois, "m"+i);
				if(moyenneDuMoisStr.isBlank()) moyenneDuMoisStr = "0";
				donnees.add(Float.parseFloat(moyenneDuMoisStr));
			}

		}catch(Exception e) {
			e.printStackTrace();
		}
		
		return donnees;
	}
	
	protected static List<Float> extraireDonneesDesJours(String xml){
		Journal.ecrire(Journal.NIVEAU.ROULEMENT, "AppuiDeBoutonDAO.extraireDonneesDesJours()");
		
		List<Float> donnees = new ArrayList<Float>();
		
		try {
			DocumentBuilder parseur = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document document = parseur.parse(new ByteArrayInputStream(xml.getBytes()));
			NodeList noeudListJours = document.getElementsByTagName("moyenne_jours");
			Element elementListJours = (Element) noeudListJours.item(0);
			
			for (int i = 0 ; i < 31 ; i++) {
				String moyenneDuJourStr = recupererElementText(elementListJours, "j"+i);
				if(moyenneDuJourStr.isBlank()) moyenneDuJourStr = "0";
				donnees.add(Float.parseFloat(moyenneDuJourStr));
			}

		}catch(Exception e) {
			e.printStackTrace();
		}
		
		return donnees;
	}
	
	protected static List<Float> extraireDonneesDesHeures(String xml){
		Journal.ecrire(Journal.NIVEAU.ROULEMENT, "AppuiDeBoutonDAO.extraireDonneesDesHeures()");
		
		List<Float> donnees = new ArrayList<Float>();
		
		try {
			DocumentBuilder parseur = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document document = parseur.parse(new ByteArrayInputStream(xml.getBytes()));
			NodeList noeudListHeures = document.getElementsByTagName("moyenne_heures");
			Element elementListHeures = (Element) noeudListHeures.item(0);
			
			for (int i = 0 ; i < 24 ; i++) {
				String moyenneDuHeuresStr = recupererElementText(elementListHeures, "h"+i);
				if(moyenneDuHeuresStr.isBlank()) moyenneDuHeuresStr = "0";
				donnees.add(Float.parseFloat(moyenneDuHeuresStr));
			}

		}catch(Exception e) {
			e.printStackTrace();
		}
		
		return donnees;
	}
	
	
	protected static String recupererElementText(Element elementParentXml, String nomElement) {
		Node element = elementParentXml.getElementsByTagName(nomElement).item(0);
		return (null != element) ? element.getTextContent() : "";
	}
}