package de.ugoe.cs.swe.exercises.lectureevent;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

import de.ugoe.cs.swe.exercises.exercisesheet.ExerciseSheet;
import de.ugoe.cs.swe.exercises.lecture.Lecture;
import de.ugoe.cs.swe.exercises.lecturer.Lecturer;
import de.ugoe.cs.swe.exercises.misc.Model;

public class LectureEvent extends Model {
	public static boolean SS = true;
	public static boolean WS = false;
	private int semester;
	private boolean isSummerSemester;
	private int lectureId;

	public LectureEvent() {

	}

	public LectureEvent(int id, int semester, boolean isSummerSemester,
			int lectureId) {
		super(id);
		this.semester = semester;
		this.isSummerSemester = isSummerSemester;
		this.lectureId = lectureId;
	}

	public LectureEvent(int semester, boolean isSummerSemester, int lectureId) {
		super();
		this.semester = semester;
		this.isSummerSemester = isSummerSemester;
		this.lectureId = lectureId;
	}

	public LectureEvent(int semester, boolean isSummerSemester, Lecture lecture) {
		super();
		this.semester = semester;
		this.isSummerSemester = isSummerSemester;
		this.lectureId = lecture.getId();
	}

	@Override
	public String toString() {
		if (!isSummerSemester) {
			int nextYear = getSemester()+1;
			return (getLecture().getName() + " (" + getSemesterString() + " " + getSemester() + "/" + nextYear + ")");
		} else {
			return (getLecture().getName() + " (" + getSemesterString() + " " + getSemester() + ")");
		}
	}

	@Override
	protected String getTableName() {
		return "lectureevent";
	}

	public int getSemester() {
		return semester;
	}

	public void setSemester(int semester) {
		this.semester = semester;
	}

	public boolean getIsSummerSemester() {
		return isSummerSemester;
	}

	public void setIsSummerSemester(boolean summer) {
		this.isSummerSemester = summer;
	}

	public Lecture getLecture() {
		return Lecture.get(lectureId);
	}

	public void setLecture(Lecture lecture) {
		this.lectureId = lecture.getId();
	}

	public String getSemesterString() {
		if (isSummerSemester)
			return "SS";
		else
			return "WS";
	}

	@Override
	protected void update() throws SQLException {
		PreparedStatement statement = prepareStatement("UPDATE lectureevent SET semester=?, ss_ws=?, lecture=? WHERE id=?");
		statement.setInt(4, this.getId());
		executeSaveStatement(statement);
	}

	protected void executeSaveStatement(PreparedStatement statement)
			throws SQLException {
		statement.setInt(1, this.getSemester());
		statement.setString(2, this.getSemesterString());
		if (this.getLecture().getId() == Model.UNDEFINED)
			throw new Model.DoesNotExistException(
					"Lecture does not exist in the database, yet");
		statement.setInt(3, this.lectureId);
		statement.executeUpdate();
	}

	@Override
	protected PreparedStatement insert() throws SQLException {
		PreparedStatement statement = prepareStatement("INSERT INTO lectureevent (semester, ss_ws, lecture) VALUES (?,?,?)");
		executeSaveStatement(statement);
		return statement;
	}

	public static ArrayList<LectureEvent> all() {
		try {
			return fromStatement(prepareStatement("SELECT * FROM lectureevent"));
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static ArrayList<LectureEvent> fromStatement(
			PreparedStatement statement) throws SQLException {
		ResultSet resultset = statement.executeQuery();
		ArrayList<LectureEvent> lectureEvents = new ArrayList<LectureEvent>();
		while (resultset.next()) {
			lectureEvents.add(new LectureEvent(resultset.getInt("id"),
					resultset.getInt("semester"), resultset.getString("ss_ws")
							.equals("SS"), resultset.getInt("lecture")));
		}
		return lectureEvents;
	}

	public ArrayList<Lecturer> getLecturers() {
		try {
			PreparedStatement statement = prepareStatement("SELECT DISTINCT lecturer.* FROM lecturer, lectureevent, lectureevent_lecturer WHERE lectureevent.id = ? AND lectureevent.id = lectureevent_lecturer.lectureevent AND lectureevent_lecturer.lecturer = lecturer.id ORDER BY id");
			statement.setInt(1, this.getId());
			return Lecturer.fromStatement(statement);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

//	private boolean lecturerAlreadyExists(Lecturer lecturer) {
//		for (Lecturer myLecturer : this.getLecturers()) {
//			if (myLecturer.getId() == lecturer.getId())
//				return true;
//		}
//
//		return false;
//	}

	public void addLecturer(Lecturer lecturer) {
		if (this.getId() == Model.UNDEFINED)
			throw new Model.DoesNotExistException(
					"Lecture event does not exist in the database, yet");
		if (lecturer.getId() == Model.UNDEFINED)
			throw new Model.DoesNotExistException(
					"Lecturer does not exist in the database, yet");
//		if (lecturerAlreadyExists(lecturer))
//			throw new Model.DoesNotExistException(
//					"Lecturer is already existant");

		PreparedStatement statement;
		try {
			statement = prepareStatement("INSERT INTO lectureevent_lecturer (lectureevent, lecturer) VALUES (?,?)");
			statement.setInt(1, this.getId());
			statement.setInt(2, lecturer.getId());
			statement.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public void clearLecturers() {
		ArrayList<Lecturer> lecturerArrayList = getLecturers();
		for (int i = 0; i < lecturerArrayList.size(); i++) {
			removeLecturer(lecturerArrayList.get(i));
		}
	}

	public void removeLecturer(Lecturer lecturer) {
		if (this.getId() == Model.UNDEFINED)
			throw new Model.DoesNotExistException(
					"Lecture event does not exist in the database, yet");
		if (lecturer.getId() == Model.UNDEFINED)
			throw new Model.DoesNotExistException(
					"Lecturer does not exist in the database, yet");

		PreparedStatement statement;
		try {
			statement = prepareStatement("DELETE FROM lectureevent_lecturer WHERE lectureevent=? AND lecturer=?");
			statement.setInt(1, this.getId());
			statement.setInt(2, lecturer.getId());
			statement.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public ArrayList<ExerciseSheet> getExerciseSheets() {
		try {
			PreparedStatement statement = prepareStatement("SELECT DISTINCT exercisesheet.* FROM exercisesheet, lectureevent WHERE lectureevent.id = ? AND lectureevent.id = exercisesheet.lectureevent ORDER BY id");
			statement.setInt(1, this.getId());
			return ExerciseSheet.fromStatement(statement);
		} catch (SQLException e) {
			System.err
					.println("Got an exception in LectureEvent.getExerciseSheets()! ");
			System.err.println(e.getMessage());
		}
		return null;
	}

	public static LectureEvent get(int lectureEventId) {
		try {
			PreparedStatement statement = prepareStatement("SELECT * FROM lectureevent WHERE id=?");
			statement.setInt(1, lectureEventId);
			return fromStatement(statement).get(0);
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (IndexOutOfBoundsException e) {
		}
		throw new Model.DoesNotExistException();
	}
}
