package controller.console.enseignant;

import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Scanner;

import view.console.enseignant.QCM_Creation;
import view.console.enseignant.QCM_Modification;

import model.Enseignant;
import model.QCM;
import model.Question;
import model.Reponse;
import model.list.HandlerQCM;

public class QCM_ModificationControle {
	private Scanner sc;
	
	private ArrayList<QCM> liste_qcm;
	private QCM qcm;
	
	private class InputDone extends Exception {
		private static final long serialVersionUID = 1L;
	}
	
	private class EditElse extends Exception {
		private static final long serialVersionUID = 1L;
	}
	
	public QCM_ModificationControle(ArrayList<QCM> liste_qcm, Enseignant e_connected) {
		boolean done = false;
		this.liste_qcm = HandlerQCM.getOwnAndPublic(e_connected, liste_qcm);
		sc = new Scanner(System.in);
		
		QCM_Modification.trigger();
		while (!done) {
			QCM_Modification.showQCM(this.liste_qcm);
			try {
				this.getQCM();
				this.editQCM();
			} catch (InputMismatchException e) {
				QCM_Modification.fail(0,this.liste_qcm.size());
			} catch (InputDone e) {
				done = true;
			}
		}
	}
	
	private void getQCM() throws InputMismatchException, InputDone {
		String str_input;
		int input;

		str_input = sc.nextLine();
		try {
			input = Integer.parseInt(str_input);
			if ((input < 0) || (input > this.liste_qcm.size())) {
				throw new InputMismatchException();
			} else if (input == 0) {
				throw new InputDone();
			} else {
				this.qcm = this.liste_qcm.get(input-1);
			}
		} catch (NumberFormatException e) {
			throw new InputMismatchException();
		}
	}
	
	private void editQCM() {
		boolean done = false;
		Question q;
		
		while (!done) {
			try {
				QCM_Modification.showQuestions(this.qcm);
				q = this.askQuestion();
				this.editQuestion(q);
			} catch (InputDone e) {
				done = true;
			} catch (InputMismatchException e) {
				QCM_Modification.fail(0,this.qcm.getQuestions().size()+3);
			} catch (EditElse e) {
				
			}
		}
	}
	
	private Question askQuestion() throws InputDone, EditElse {
		String str_input;
		int input;

		str_input = sc.nextLine();
		try {
			input = Integer.parseInt(str_input);
			if ((input < 0) || (input > this.qcm.getQuestions().size()+3)) {
				throw new InputMismatchException();
			} else if (input == 0) {
				throw new InputDone();
			} else if (input == 1) {
				QCM_Modification.askLibelle();
				this.askLibQCM();
				throw new EditElse();
			} else if (input == 2) {
				this.qcm.setPrive(!this.qcm.isPrive());
				QCM_Modification.tellPrive(this.qcm.isPrive());
				throw new EditElse();
			} else if (input == 3) {
				QCM_Modification.addQuestion(this.qcm.getQuestions().size());
				this.addQuestion();
				throw new EditElse();
			} else {
				return this.qcm.getQuestions().get(input-4);
			}
		} catch (NumberFormatException e) {
			throw new InputMismatchException();
		}
	}
	
	private void editQuestion(Question q) throws InputDone {
		boolean done = false;
		Reponse r;
		
		while (!done) {
			try {
				QCM_Modification.showReponses(q);
				r = this.askReponse(q);
				this.editReponse(r,q);
			} catch (InputDone e) {
				done = true;
			} catch (InputMismatchException e) {
				QCM_Modification.fail(0,q.getReponses().size()+3);
			} catch (EditElse e) {
				
			}
		}
	}
	
	private Reponse askReponse(Question q) throws InputDone, EditElse {
		String str_input;
		int input;

		str_input = sc.nextLine();
		try {
			input = Integer.parseInt(str_input);
			if ((input < 0) || (input > q.getReponses().size()+3)) {
				throw new InputMismatchException();
			} else if (input == 0) {
				throw new InputDone();
			} else if (input == 1) {
				QCM_Modification.removeQuestion(q);
				this.qcm.getQuestions().remove(q);
				throw new InputDone();
			} else if (input == 2) {
				QCM_Modification.addReponse(q.getReponses().size());
				q.getReponses().add(this.addReponse());
				throw new EditElse();
			} else if (input == 3) {
				QCM_Modification.askQuestion();
				this.askLibQuestion(q);
				throw new EditElse();
			} else {
				return q.getReponses().get(input-4);
			}
		} catch (NumberFormatException e) {
			throw new InputMismatchException();
		}
	}
	
	private void editReponse(Reponse r, Question q) throws InputDone {
		boolean done = false;
		
		while (!done) {
			try {
				QCM_Modification.editReponse(r);
				this.askField(r,q);
			} catch (InputDone e) {
				done = true;
			} catch (InputMismatchException e) {
				QCM_Modification.fail(-1,2);
			}
		}
	}
	
	private void askField(Reponse r, Question q) throws InputDone {
		int input;
		input = sc.nextInt();
		sc.nextLine();

		if (input < -1 || input > 2) {
			throw new InputMismatchException();
		} else {
			if (input == -1) {
				QCM_Modification.removeReponse(r);
				q.getReponses().remove(r);
				throw new InputDone();
			} else if (input == 0) {
				throw new InputDone();
			} else if (input == 1) {
				QCM_Modification.askReponse();
				this.askLibReponse(r);
			} else if (input == 2) {
				r.setVraie(!r.isVraie());
				QCM_Modification.tellVraie(r.isVraie());
			}
		}
	}
	
	private void askLibQCM() {
		String input = sc.nextLine();
		this.qcm.setLibelle(input);
	}
	
	private void askLibQuestion(Question q) {
		String input = sc.nextLine();
		q.setLibelle(input);
	}
	
	private void askLibReponse(Reponse r) {
		String input = sc.nextLine();
		r.setLibelle(input);
	}
	
	private void addQuestion() {
		String libelle_qu;
		ArrayList<Reponse> lReponses = new ArrayList<Reponse>();
		boolean done = false;
		int count_r = 0;
		libelle_qu = sc.nextLine();
		while (!done) {
			count_r++;
			QCM_Creation.showReponses(libelle_qu, lReponses);
			QCM_Modification.addReponse(count_r);
			lReponses.add(this.addReponse());
			QCM_Modification.askDoneReponse();
			done = !this.askBoolean();
		}
		this.qcm.getQuestions().add(new Question(libelle_qu,lReponses));
	}
	
	private Reponse addReponse() {
		String libelle_r;
		boolean vraie = false;
		
		libelle_r = sc.nextLine();
		QCM_Creation.askVraie();
		vraie = this.askBoolean();
		
		return (new Reponse(libelle_r, vraie));
	}
	
	private boolean askBoolean() {
		String input = sc.nextLine();
		return (input.startsWith("o") || input.startsWith("O"));
	}
	
	public void updateDatabase() {
		QCM_Modification.updateDatabase();
	}
}
