import schedule.Lecture;
import schedule.Schedule;
import time.Time;

public class Test {

	static int score = 0;

	private static Time time1;
	private static Time time2;
	private static Lecture lecture1;
	private static Lecture lecture6;
	private static Lecture lecture2;
	private static Lecture lecture3;
	private static Time time3;
	private static Time time7;

	public static void main(String[] args) {

		testTime();
		testLecture();
		testSchedule();
		testParseTime();
		testParseLecture();

		System.out.println("Pontszam: " + score);

		if(score < 10) System.out.println("Jegy: elegtelen (1)");
		else if(score < 14) System.out.println("Jegy: elegseges (2)");
		else if(score < 18) System.out.println("Jegy: kozepes (3)");
		else if(score < 23) System.out.println("Jegy: jo (4)");
		else System.out.println("Jegy: jeles (5)");

	}

	private static void testTime() {
		testTimeConstants();

		time1 = Time.create(Time.WEDNESDAY, 8, 30);
		time2 = Time.create(Time.WEDNESDAY, 10, 00);
		time3 = Time.create(Time.WEDNESDAY, 10, 00);

		assertTrue("Parameters for time1 are valid", time1 != null);
		assertTrue("Parameters for time2 are valid", time2 != null);
		assertTrue("Parameters for time3 are valid", time3 != null);

		score = score + 1;

		Time time4 = Time.create(Time.WEDNESDAY, 24, 00);
		Time time5 = Time.create(Time.WEDNESDAY, 00, 60);
		Time time6 = Time.create(7, 00, 00);

		assertTrue("Parameters for time4 are not valid", time4 == null);
		assertTrue("Parameters for time5 are not valid", time5 == null);
		assertTrue("Parameters for time6 are not valid", time6 == null);

		score = score + 1;

		testTimeIsSame();

		testTimeBefore();

		time7 = Time.create(Time.WEDNESDAY, 8, 45);

		testTimeBetween();

		testTimeShow();

		System.out.println("Time: OK (" + score + " total)");
	}

	private static void testTimeConstants() {
		assertTrue("MONDAY != 0", Time.MONDAY == 0);
		assertTrue("TUESDAY != 1", Time.TUESDAY == 1);
		assertTrue("WEDNESDAY != 2", Time.WEDNESDAY == 2);
		assertTrue("THURSDAY != 3", Time.THURSDAY == 3);
		assertTrue("FRIDAY != 4", Time.FRIDAY == 4);
		assertTrue("SATURDAY != 5", Time.SATURDAY == 5);
		assertTrue("SUNDAY != 6", Time.SUNDAY == 6);

		score = score + 1;
	}

	private static void testTimeIsSame() {
		assertTrue("10:00 == 10:00", time2.isSame(time2));
		assertTrue("10:00 == 10:00", time2.isSame(time3));
		assertFalse("8:30 != 10:00", time1.isSame(time2));

		score = score + 1;
	}

	private static void testTimeBefore() {
		assertTrue("8:30 >= 10:00", time1.before(time2));
		assertFalse("10:00 < 10:00", time2.before(time3));

		score = score + 3;
	}

	private static void testTimeBetween() {
		assertTrue("time1 < time7 < time2", time7.between(time1, time2));
		assertFalse("time1 < time2 < time3", time2.between(time1, time3));
		assertFalse("time1 < time2 < time7", time2.between(time1, time7));

		score = score + 1;
	}

	private static void testTimeShow() {
		assertTrue("time1.show() !== WED 8:30",
				Time.create(Time.WEDNESDAY, 8, 30).show().equals("WED 8:30"));

		score = score + 2;
	}

	private static void testLecture() {
		lecture1 = Lecture.create("Programozasi Nyelvek II. Java 4", false,
				time1, time2);
		lecture2 = Lecture.create("a", false, time2,
				Time.create(Time.WEDNESDAY, 11, 30));
		lecture3 = Lecture.create("b", false,
				Time.create(Time.WEDNESDAY, 8, 15),
				Time.create(Time.WEDNESDAY, 9, 45));
		Lecture lecture4 = Lecture.create("c", false, time2, time1);
		Lecture lecture5 = Lecture.create("d", false, time2, null);
		lecture6 = Lecture.create("e", true,
				Time.create(Time.WEDNESDAY, 8, 15),
				Time.create(Time.WEDNESDAY, 9, 45));

		assertFalse("lecture1 is not a consultation", lecture1.isConsultation());

		score = score + 1;

		assertTrue("lecture1's parameters are correct", lecture1 != null);
		assertTrue("lecture2's parameters are correct", lecture2 != null);
		assertTrue("lecture3's parameters are correct", lecture3 != null);
		assertTrue("lecture4's parameters are not correct", lecture4 == null);
		assertTrue("lecture5's parameters are not correct", lecture5 == null);
		assertTrue("lecture6's parameters are correct", lecture6 != null);

		score = score + 2;

		testLectureOverlap();

		testLectureShow();

		System.out.println("Lecture: OK (" + score + " total)");
	}

	private static void testLectureOverlap() {
		assertFalse("lecture1 and lecture2 should not overlap.",
				lecture1.overlapsWith(lecture2));

		assertTrue("lecture1 and lecture3 should overlap.",
				lecture1.overlapsWith(lecture3));

		assertTrue("lecture1 should overlap with itself.",
				lecture1.overlapsWith(lecture1));

		score = score + 1;
	}

	private static void testLectureShow() {
		assertEquals("lecture1.show()",
				"Programozasi Nyelvek II. Java 4 WED 8:30 - WED 10:00",
				lecture1.show());

		assertEquals("lecture6.show()", "e (CONSULTATION) WED 8:15 - WED 9:45",
				lecture6.show());

		score = score + 2;
	}

	private static void testSchedule() {

		Schedule schedule1 = new Schedule();

		schedule1.addLecture(lecture1);
		schedule1.addLecture(lecture2);
		schedule1.addLecture(lecture6);

		Schedule schedule2 = new Schedule();

		schedule2.addLecture(lecture1);
		schedule2.addLecture(lecture3);

		testScheduleCheck(schedule1, schedule2);

		testScheduleList(schedule1);

		System.out.println("Schedule: OK (" + score + " total)");

	}

	private static void testScheduleCheck(Schedule schedule1, Schedule schedule2) {
		assertTrue("schedule1 is OK, because lecture6 is a consultation.",
				schedule1.scheduleIsOK());
		assertFalse("schedule2 is not OK.", schedule2.scheduleIsOK());

		score = score + 3;
	}

	private static void testScheduleList(Schedule schedule1) {
		assertEquals("schedule1.listLectures()",
				"Programozasi Nyelvek II. Java 4 WED 8:30 - WED 10:00\n"
						+ "a WED 10:00 - WED 11:30\n"
						+ "e (CONSULTATION) WED 8:15 - WED 9:45",
				schedule1.listLectures().trim());

		score = score + 3;
	}

	private static void testParseTime() {
		Time parseTime1 = Time.parseTime("WED 12:00");
		Time parseTime2 = Time.parseTime("WED 13:00");

		assertTrue("parseTime1 is created from text in the normal format.", parseTime1 != null);
		assertTrue("parseTime2 is created from text in the normal format.", parseTime2 != null);

		assertTrue("parseTime1 >= parseTime2", parseTime1.before(parseTime2));

		score = score + 2;

		Time parseTime3 = Time.parseTime("WE 13:00");
		Time parseTime4 = Time.parseTime("WED 0:60");
		Time parseTime5 = Time.parseTime("00:00");

		assertTrue("parseTime3 is created from invalid text.", parseTime3 == null);
		assertTrue("parseTime4 is created from invalid text.", parseTime4 == null);
		assertTrue("parseTime5 is created from invalid text.", parseTime5 == null);

		score = score + 1;

		System.out.println("Parse Time: OK (" + score + " total)");
	}

	private static void testParseLecture() {
		Lecture parseLecture1 = Lecture.parseLecture(
				"Programozasi Nyelvek II. Java 4", "WED 8:30", "WED 10:00");
		Lecture parseLecture2 = Lecture.parseLecture(
				"x (CONSULTATION)", "WED 8:30", "WED 10:00");

		assertTrue("parseLecture1 is created from text in the normal format.", parseLecture1 != null);

		assertTrue("parseLecture1 overlapsWith parseLecture2", parseLecture1.overlapsWith(parseLecture2));

		assertFalse("parseLecture1 is not a consultation", parseLecture1.isConsultation());

		assertTrue("parseLecture2 is a consultation", parseLecture2.isConsultation());

		score = score + 2;

		System.out.println("Parse Lecture: OK (" + score + " total)");
	}

	private static void assertFalse(String msg, boolean p) {
		if (p) {
			throw new RuntimeException(msg);
		}
	}

	private static void assertTrue(String msg, boolean p) {
		if (!p) {
			throw new RuntimeException(msg);
		}
	}

	private static void assertEquals(String msg, Object expected, Object actual) {
		if (!expected.equals(actual)) {
			throw new RuntimeException(msg + "\nexpected:\n" + expected
					+ "\nactual:\n" + actual);
		}
	}

}