package model.list;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import model.Eleve;
import model.Rendu;
import model.Session;
import model.Reponse;
import model.Utilisateur;

public class HandlerRendus extends DefaultHandler {
	private final DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
	
	private int balise = 0;
	
	private Date dateRendu;
	private Eleve eleve;
	private Session session;
	private ArrayList<Reponse> reponsesChoisies;
	
	private ArrayList<Utilisateur> lUtil;
	private ArrayList<Session> lSess;
	
	private ArrayList<Rendu> liste;
	
	public HandlerRendus(ArrayList<Utilisateur> lUtil, ArrayList<Session> lSess) {
		super();
		this.lUtil = lUtil;
		this.lSess = lSess;
		this.reponsesChoisies = new ArrayList<Reponse>();
		this.liste = new ArrayList<Rendu>();
	}
	
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		if (qName.equals("dateRendu")) {
			balise = 1;
		} else if (qName.equals("eleve")) {
			balise = 2;
		} else if (qName.equals("session")) {
			balise = 3;
		} else if (qName.equals("reponse")) {
			balise = 4;
		}
	}
	
	public void characters(char ch[], int start, int length) throws SAXException {
		String input = new String(ch, start, length);
		try {
			switch (balise) {
			case 1 : this.dateRendu = this.dateFormat.parse(input);
			break;
			case 2 : this.eleve = (Eleve) HandlerUtilisateurs.getUtilisateur(input, lUtil);
			break;
			case 3 : this.session = HandlerSessions.getSession(Integer.parseInt(input), lSess);
			break;
			case 4 : this.reponsesChoisies.add(this.session.getQcm().getReponse(Integer.parseInt(input)));
			break;
			}
		} catch (ParseException e) {
			throw new SAXException("Dates must be in dd-MM-yyyy form.");
		} catch (NumberFormatException e) {
			throw new SAXException("Expected integer inside of element.");
		}
	}
	
	public void endElement(String uri, String localName, String qName) throws SAXException {
		switch (qName) {
		case "dateRendu" : case "eleve" : case "session" : case "reponse" : balise = 0;
		break;
		case "rendu" : this.liste.add(new Rendu(this.dateRendu, this.eleve, this.session, this.reponsesChoisies));
		break;
		}
	}
	
	public ArrayList<Rendu> getListe() {
		return this.liste;
	}
	
	public static ArrayList<Rendu> getFromSession(Session s, ArrayList<Rendu> lRendu) {
		int i;
		ArrayList<Rendu> res = new ArrayList<Rendu>();
		for (i = 0 ; i < lRendu.size() ; i++) {
			if (lRendu.get(i).getSession().equals(s)) {
				res.add(lRendu.get(i));
			}
		}
		return res;
	}
	
	public static ArrayList<Rendu> getListeForEleve(Session s, Eleve e, ArrayList<Rendu> lRendu) {
		int i;
		ArrayList<Rendu> res = new ArrayList<Rendu>();
		for (i = 0 ; i < lRendu.size() ; i++) {
			if (lRendu.get(i).getSession().equals(s)) {
				if (lRendu.get(i).getEleve().equals(e)) {
					res.add(lRendu.get(i));
				}
			}
		}
		return res;
	}
	
	public static int getTimesAnswered(Session s, Eleve e, ArrayList<Rendu> lRendu) {
		int i;
		int count = 0;
		for (i = 0 ; i < lRendu.size() ; i++) {
			if (lRendu.get(i).getSession().equals(s)) {
				if (lRendu.get(i).getEleve().equals(e)) {
					count++;
				}
			}
		}
		return count;
	}
	
	public void updateDatabase() {
		int i;
		try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("bin/data/Rendu.xml"), "utf-8"))) {
			writer.write("<?xml version=\"1.0\"?>\n");
			writer.write("<rendus>\n	");
			for (i = 0 ; i < this.liste.size() ; i++) {
				this.writeRendu(writer,this.liste.get(i));
			}
		    writer.write("\n</rendus>");
		} catch (IOException e) {
		    System.out.println("Error: Database update failed.");
		}  
	}
	
	private void writeRendu(Writer w, Rendu r) throws IOException {
		int i;
		w.write("<rendu>\n		");
		w.write("<dateRendu>" + dateFormat.format(r.getDateRendu()) + "</dateRendu>\n		");
		w.write("<eleve>" + r.getEleve().getLogin() + "</eleve>\n		");
		w.write("<session>" + Integer.toString(r.getSession().getId()) + "</session>\n		");
		for (i = 0 ; i < r.getReponsesChoisies().size() ; i++) {
			w.write("<reponse>" + Integer.toString(r.getReponsesChoisies().get(i).getId()) + "</reponse>\n		");
		}
		w.write("\n	</rendu>\n	");
	}
}
