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 model.Enseignant;
import model.Module;
import model.Promotion;
import model.QCM;
import model.Session;
import model.Utilisateur;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class HandlerSessions extends DefaultHandler {
	private final DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
	
	private int balise = 0;
	private ArrayList<Utilisateur> lUtil;
	private ArrayList<Promotion> lPromo;
	private ArrayList<Module> lMod;
	private ArrayList<QCM> lQCM;
	
	private int id;
	private Date dateDebut;
	private Date dateFin;
	private int repetition;
	private Enseignant createur;
	private Promotion promotion;
	private Module module;
	private QCM qcm;
	
	private ArrayList<Session> liste;
	
	public HandlerSessions(ArrayList<Utilisateur> lUtil, ArrayList<Promotion> lPromo, ArrayList<Module> lMod, ArrayList<QCM> lQCM) {
		super();
		this.liste = new ArrayList<Session>();
		this.lUtil = lUtil;
		this.lPromo = lPromo;
		this.lMod = lMod;
		this.lQCM = lQCM;
	}
	
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		try {
			for (int i = 0 ; i < attributes.getLength() ; i++) {
				if (attributes.getQName(i).equals("dateDebut")) {
					this.dateDebut = dateFormat.parse(attributes.getValue(i));
				} else if (attributes.getQName(i).equals("dateFin")) {
					this.dateFin = dateFormat.parse(attributes.getValue(i));
				} else if (attributes.getQName(i).equals("repetition")) {
					this.repetition = Integer.parseInt(attributes.getValue(i));
				}
			}
		} catch (ParseException e) {
			throw new SAXException("Dates must be in dd-MM-yyyy form.");
		} catch (NumberFormatException e) {
			throw new SAXException("'repetition' attribute must be an integer.");
		}
		if (qName.equals("createur")) {
			balise = 1;
		} else if (qName.equals("promotion")) {
			balise = 2;
		} else if (qName.equals("module")) {
			balise = 3;
		} else if (qName.equals("qcm")) {
			balise = 4;
		} else if (qName.equals("id")) {
			balise = 5;
		}
	}
	
	public void characters(char ch[], int start, int length) throws SAXException {
		String input = new String(ch, start, length);
		switch (balise) {
		case 1 : this.createur = (Enseignant) HandlerUtilisateurs.getUtilisateur(input, this.lUtil);
		break;
		case 2 : this.promotion = HandlerPromotions.getPromotion(input, lPromo);
		break;
		case 3 : this.module = HandlerModules.getModule(input, lMod);
		break;
		case 4 : this.qcm = HandlerQCM.getQCM(input, lQCM);
		break;
		case 5 : this.id = Integer.parseInt(input);
		}
	}
	
	public void endElement(String uri, String localName, String qName) throws SAXException {
		switch (qName) {
		case "createur" : case "promotion" : case "module" : case "qcm" : case "id" : balise = 0;
		break;
		case "session" : this.liste.add(new Session(this.id, this.dateDebut, this.dateFin, this.repetition, this.createur, this.promotion, this.module, this.qcm));
		break;
		}
	}
	
	public ArrayList<Session> getListe() {
		return this.liste;
	}
	
	public static ArrayList<Session> getOwn(Enseignant e, ArrayList<Session> lSess) {
		int i;
		ArrayList<Session> res = new ArrayList<Session>();
		for (i = 0 ; i < lSess.size() ; i++) {
			if (lSess.get(i).getCreateur().equals(e)) {
				res.add(lSess.get(i));
			}
		}
		return res;
	}
	
	public static Session getSession(int hash, ArrayList<Session> lSess) {
		int i = 0;
		int tmp = 0;
		while (!(hash == tmp) && (i < lSess.size())) {
			tmp = lSess.get(i).getId();
			i++;
		}
		if (tmp == hash) {
			return lSess.get(i-1);
		} else {
			return null;
		}
	}
	
	/**
	 * Séparation des sessions en cours et des sessions finies
	 * @param mode TRUE : Mode "en cours" ; FALSE : Mode "fini"
	 * @return Liste des sessions en cours (ou non)
	 */
	public ArrayList<Session> getEnCours(boolean mode) {
		int i;
		ArrayList<Session> res = new ArrayList<Session>();
		for (i = 0 ; i < this.liste.size(); i++) {
			if (this.liste.get(i).isEnCours() == mode) {
				res.add(this.liste.get(i));
			}
		}
		return res;
	}
	
	public void updateDatabase() {
		int i;
		try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("bin/data/Session.xml"), "utf-8"))) {
			writer.write("<?xml version=\"1.0\"?>\n");
			writer.write("<sessions>\n	");
			for (i = 0 ; i < this.liste.size() ; i++) {
				this.writeSession(writer,this.liste.get(i));
			}
		    writer.write("\n</sessions>");
		} catch (IOException e) {
		    System.out.println("Error: Database update failed.");
		}  
	}
	
	private void writeSession(Writer w, Session s) throws IOException {
		w.write("<session dateDebut=\"" + this.dateFormat.format(s.getDateDebut()));
		w.write("\" dateFin=\"" + this.dateFormat.format(s.getDateFin()));
		w.write("\" repetition=\"" + Integer.toString(s.getRepetition()));
		w.write("\">\n		");
		w.write("<id>" + s.getId() + "</id>\n		");
		w.write("<createur>" + s.getCreateur().getLogin() + "</createur>\n		");
		w.write("<promotion>" + s.getPromotion().getLibelle() + "</promotion>\n		");
		w.write("<module>" + s.getModule().getLibelle() + "</module>\n		");
		w.write("<qcm>" + s.getQcm().getLibelle() + "</qcm>\n		");
		w.write("\n	</session>\n	");
	}
}
