package dst.ass1.jpa.tests;

import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import javax.persistence.EntityManager;

import dst.ass1.jpa.ITestData;
import dst.ass1.jpa.model.CourseStatus;
import dst.ass1.jpa.model.IAddress;
import dst.ass1.jpa.model.ICourse;
import dst.ass1.jpa.model.ICoursePlatform;
import dst.ass1.jpa.model.IEnrollment;
import dst.ass1.jpa.model.IEnrollmentKey;
import dst.ass1.jpa.model.ILecturer;
import dst.ass1.jpa.model.ILesson;
import dst.ass1.jpa.model.IMaterial;
import dst.ass1.jpa.model.IMaterialServer;
import dst.ass1.jpa.model.IMembership;
import dst.ass1.jpa.model.IMetadata;
import dst.ass1.jpa.model.IModelFactory;
import dst.ass1.jpa.model.IParticipant;

/**
 * Test data used by the default set of tests.
 */
public class TestData implements ITestData {

    public static final String COURSE_PLATFORM_1_NAME = "coursePlatform1";
    public static final String COURSE_PLATFORM_2_NAME = "coursePlatform2";
    public static final String COURSE_1_NAME = "course1";
    public static final String COURSE_2_NAME = "course2";
    public static final String COURSE_3_NAME = "course3";
    public static final String COURSE_4_NAME = "course4";
    public static final String MATERIAL_SERVER_1_NAME = "materialServer1";
    public static final String MATERIAL_SERVER_2_NAME = "materialServer2";
    public static final String MATERIAL_SERVER_3_NAME = "materialServer3";
    public static final String MATERIAL_1_URN = "material1";
    public static final String MATERIAL_2_URN = "material2";
    public static final String MATERIAL_3_URN = "material3";
    public static final String MATERIAL_4_URN = "material4";
    public static final String MATERIAL_5_URN = "material5";
    public static final String METADATA_1_KEY_1 = "key11";
    public static final String METADATA_1_VALUE_1 = "setting11";
    public static final String METADATA_1_KEY_2 = "key12";
    public static final String METADATA_1_VALUE_2 = "setting12";
    public static final String METADATA_2_KEY_1 = "key21";
    public static final String METADATA_2_VALUE_1 = "setting21";
    public static final String LECTURER_1_NAME = "Alex";
    public static final String LECTURER_2_NAME = "Alexandra";
    public static final String LECTURER_3_NAME = "Alexander";
    public static final String PARTICIPANT_1_NAME = "Participant1";
    public static final String PARTICIPANT_1_PW = "pw4";
    public static final String PARTICIPANT_1_ACCOUNT_NO = "account1";
    public static final String PARTICIPANT_1_BANK_CODE = "bank1";
    public static final String PARTICIPANT_1_EMAIL = PARTICIPANT_1_NAME + "@example.com";
    public static final String PARTICIPANT_2_NAME = "Participant2";
    public static final String PARTICIPANT_2_PW = "pw5";
    public static final String PARTICIPANT_2_ACCOUNT_NO = "account2";
    public static final String PARTICIPANT_2_BANK_CODE = "bank2";
    public static final String PARTICIPANT_2_EMAIL = PARTICIPANT_2_NAME + "@example.com";
    public static final String LESSON_1_DESC = "Advanced Enterprise Cloud Machine Learning";
    public static final String LESSON_2_DESC = "Why you should invest in Bitcoin right now";
    public static final String LESSON_3_DESC = "Blockchain for whatever domain your company works in";
    public static final String LESSON_4_DESC = "The Dark Net and other terrible things";
    public static final String LESSON_5_DESC = "Build nano-services to solve all your problems";

    public Long lecturer1Id;
    public Long lecturer2Id;
    public Long lecturer3Id;
    public Long participant1Id;
    public Long participant2Id;
    public Long membership1Id;
    public Long membership2Id;
    public Long membership3Id;
    public Long lesson1Id;
    public Long lesson2Id;
    public Long lesson3Id;
    public Long lesson4Id;
    public Long lesson5Id;
    public Long coursePlatform1Id;
    public Long coursePlatform2Id;
    public Long metadata1Id;
    public Long metadata2Id;
    public Long material1Id;
    public Long material2Id;
    public Long material3Id;
    public Long material4Id;
    public Long material5Id;
    public Long materialServer1Id;
    public Long materialServer2Id;
    public Long materialServer3Id;
    public Long course1Id;
    public Long course2Id;
    public Long course3Id;
    public Long course4Id;

    public static Date createDate(int year, int month, int day, int hours, int minutes) {
        GregorianCalendar cal = new GregorianCalendar(year, month, day, hours, minutes);
        cal.setTimeZone(TimeZone.getTimeZone("UTC"));
        return cal.getTime();
    }

    @Override
    public void insert(IModelFactory modelFactory, EntityManager em) {
        MessageDigest md = getMessageDigest();

        // Addresses
        IAddress address1 = modelFactory.createAddress();
        IAddress address2 = modelFactory.createAddress();
        IAddress address3 = modelFactory.createAddress();
        IAddress address4 = modelFactory.createAddress();
        IAddress address5 = modelFactory.createAddress();

        address1.setCity("city1");
        address1.setStreet("street1");
        address1.setZipCode("zip1");

        address2.setCity("city2");
        address2.setStreet("street2");
        address2.setZipCode("zip2");

        address3.setCity("city3");
        address3.setStreet("street3");
        address3.setZipCode("zip3");

        address4.setCity("city4");
        address4.setStreet("street4");
        address4.setZipCode("zip4");

        address5.setCity("city5");
        address5.setStreet("street5");
        address5.setZipCode("zip5");

        // Lecturers
        ILecturer lecturer1 = modelFactory.createLecturer();
        ILecturer lecturer2 = modelFactory.createLecturer();
        ILecturer lecturer3 = modelFactory.createLecturer();

        lecturer1.setName(LECTURER_1_NAME);
        lecturer1.setAddress(address1);

        lecturer2.setName(LECTURER_2_NAME);
        lecturer2.setAddress(address2);

        lecturer3.setName(LECTURER_3_NAME);
        lecturer3.setAddress(address5);

        // Participants
        IParticipant participant1 = modelFactory.createParticipant();
        participant1.setName(PARTICIPANT_1_NAME);
        participant1.setAddress(address3);
        participant1.setAccountNo(PARTICIPANT_1_ACCOUNT_NO);
        participant1.setBankCode(PARTICIPANT_1_BANK_CODE);
        participant1.setEmail(PARTICIPANT_1_EMAIL);
        participant1.setPassword(md.digest(PARTICIPANT_1_PW.getBytes()));

        IParticipant participant2 = modelFactory.createParticipant();
        participant2.setName(PARTICIPANT_2_NAME);
        participant2.setAddress(address4);
        participant2.setAccountNo(PARTICIPANT_2_ACCOUNT_NO);
        participant2.setBankCode(PARTICIPANT_2_BANK_CODE);
        participant2.setEmail(PARTICIPANT_2_EMAIL);
        participant2.setPassword(md.digest(PARTICIPANT_2_PW.getBytes()));

        // Materials
        IMaterial material1 = modelFactory.createMaterial();
        material1.setUrn(MATERIAL_1_URN);
        material1.setType("MPEG");
        material1.setUploaded(new Date());
        material1.setLastUpdate(new Date());

        IMaterial material2 = modelFactory.createMaterial();
        material2.setUrn(MATERIAL_2_URN);
        material2.setType("PDF");
        material2.setUploaded(new Date());
        material2.setLastUpdate(new Date());

        IMaterial material3 = modelFactory.createMaterial();
        material3.setUrn(MATERIAL_3_URN);
        material3.setType("PNG");
        material3.setUploaded(new Date());
        material3.setLastUpdate(new Date());

        IMaterial material4 = modelFactory.createMaterial();
        material4.setUrn(MATERIAL_4_URN);
        material4.setType("PDF");
        material4.setUploaded(new Date());
        material4.setLastUpdate(new Date());

        IMaterial material5 = modelFactory.createMaterial();
        material5.setUrn(MATERIAL_5_URN);
        material5.setType("PNG");
        material5.setUploaded(new Date());
        material5.setLastUpdate(new Date());

        // Material Servers
        IMaterialServer materialServer1 = modelFactory.createMaterialServer();
        materialServer1.setName(MATERIAL_SERVER_1_NAME);
        materialServer1.setLastMaintenance(new Date());
        materialServer1.setNextMaintenance(new Date());

        IMaterialServer materialServer2 = modelFactory.createMaterialServer();
        materialServer2.setName(MATERIAL_SERVER_2_NAME);
        materialServer2.setLastMaintenance(new Date());
        materialServer2.setNextMaintenance(new Date());

        IMaterialServer materialServer3 = modelFactory.createMaterialServer();
        materialServer3.setName(MATERIAL_SERVER_3_NAME);
        materialServer3.setLastMaintenance(new Date());
        materialServer3.setNextMaintenance(new Date());

        materialServer1.addMaterial(material1);
        materialServer1.addMaterial(material2);
        material1.addMaterialServer(materialServer1);
        material2.addMaterialServer(materialServer1);

        materialServer2.addMaterial(material2);
        materialServer2.addMaterial(material3);
        materialServer2.addMaterial(material4);
        material2.addMaterialServer(materialServer2);
        material3.addMaterialServer(materialServer2);
        material4.addMaterialServer(materialServer2);

        materialServer3.addMaterial(material3);
        materialServer3.addMaterial(material4);
        materialServer3.addMaterial(material5);
        material3.addMaterialServer(materialServer3);
        material4.addMaterialServer(materialServer3);
        material5.addMaterialServer(materialServer3);

        // Metadata
        IMetadata metadata1 = modelFactory.createMetadata();
        metadata1.putData(METADATA_1_KEY_1, METADATA_1_VALUE_1);
        metadata1.putData(METADATA_1_KEY_2, METADATA_1_VALUE_2);

        IMetadata metadata2 = modelFactory.createMetadata();
        metadata1.putData(METADATA_2_KEY_1, METADATA_2_VALUE_1);

        IMetadata metadata3 = modelFactory.createMetadata();
        IMetadata metadata4 = modelFactory.createMetadata();

        // Course
        ICourse course1 = modelFactory.createCourse();
        course1.setName(COURSE_1_NAME);
        course1.setStatus(CourseStatus.CREATED);
        course1.setPremium(true);
        course1.setCost(new BigDecimal(1337));
        course1.setStart(createDate(2018, 1, 1, 8, 0));
        course1.setEnd(createDate(2019, 1, 31, 17, 0));
        course1.setCapacity(10);

        ICourse course2 = modelFactory.createCourse();
        course2.setName(COURSE_2_NAME);
        course2.setStatus(CourseStatus.ONGOING);
        course2.setPremium(false);
        course2.setCost(new BigDecimal(0));
        course2.setStart(createDate(2018, 2, 1, 8, 0));
        course2.setEnd(createDate(2019, 6, 30, 17, 0));
        course2.setCapacity(2);

        ICourse course3 = modelFactory.createCourse();
        course3.setName(COURSE_3_NAME);
        course3.setStatus(CourseStatus.ONGOING);
        course3.setPremium(true);
        course3.setCost(new BigDecimal(0));
        course3.setStart(createDate(2018, 2, 1, 8, 0));
        course3.setEnd(createDate(2019, 6, 30, 17, 0));
        course3.setCapacity(0);

        ICourse course4 = modelFactory.createCourse();
        course4.setName(COURSE_4_NAME);
        course4.setStatus(CourseStatus.CREATED);
        course4.setPremium(true);
        course4.setCost(new BigDecimal(0));
        course4.setStart(createDate(2018, 2, 1, 8, 0));
        course4.setEnd(createDate(2019, 6, 30, 17, 0));
        course4.setCapacity(10);

        course1.setMetadata(metadata1);
        course2.setMetadata(metadata2);
        course3.setMetadata(metadata3);
        course4.setMetadata(metadata4);

        course1.setLecturer(lecturer1);
        lecturer1.addCourse(course1);
        course2.setLecturer(lecturer2);
        lecturer2.addCourse(course2);

        // enrollments
        IEnrollmentKey ekey1 = modelFactory.createEnrollmentKey();
        ekey1.setParticipant(participant1);
        ekey1.setCourse(course1);

        IEnrollment enrollment1 = modelFactory.createEnrollment();
        enrollment1.setId(ekey1);
        enrollment1.setEnrolledAt(new Date());

        course1.addEnrollment(enrollment1);
        participant1.addEnrollment(enrollment1);

        IEnrollmentKey ekey2 = modelFactory.createEnrollmentKey();
        ekey2.setParticipant(participant2);
        ekey2.setCourse(course2);

        IEnrollment enrollment2 = modelFactory.createEnrollment();
        enrollment2.setId(ekey2);
        enrollment2.setEnrolledAt(new Date());

        course2.addEnrollment(enrollment2);
        participant2.addEnrollment(enrollment2);


        // Course Platform
        ICoursePlatform coursePlatform1 = modelFactory.createCoursePlatform();
        coursePlatform1.setName(COURSE_PLATFORM_1_NAME);
        coursePlatform1.setUrl("https://www.openmoocs.com");

        ICoursePlatform coursePlatform2 = modelFactory.createCoursePlatform();
        coursePlatform2.setName(COURSE_PLATFORM_2_NAME);
        coursePlatform2.setUrl("https://www.youdecity.com");

        coursePlatform1.addMaterialServer(materialServer1);
        coursePlatform1.addMaterialServer(materialServer2);
        coursePlatform2.addMaterialServer(materialServer3);

        course1.setCoursePlatform(coursePlatform1);
        course2.setCoursePlatform(coursePlatform2);
        course3.setCoursePlatform(coursePlatform2);
        course4.setCoursePlatform(coursePlatform2);

        // Memberships
        IMembership membership1 = modelFactory.createMembership();
        membership1.setDiscount(200.0);
        membership1.setPremium(true);
        membership1.setParticipant(participant1);
        membership1.setCoursePlatform(coursePlatform1);
        participant1.addMembership(membership1);

        IMembership membership2 = modelFactory.createMembership();
        membership2.setDiscount(0.0);
        membership2.setPremium(false);
        membership2.setParticipant(participant1);
        membership2.setCoursePlatform(coursePlatform2);
        participant1.addMembership(membership2);

        IMembership membership3 = modelFactory.createMembership();
        membership3.setDiscount(10.0);
        membership3.setPremium(false);
        membership3.setParticipant(participant2);
        membership3.setCoursePlatform(coursePlatform1);
        participant2.addMembership(membership3);

        // Lesson
        ILesson lesson1 = modelFactory.createLesson();
        lesson1.setDescription(LESSON_1_DESC);
        lesson1.setStart(createDate(2018, 1, 6, 11, 1)); // date in the past!
        lesson1.setEnd(createDate(2018, 1, 6, 12, 1));

        ILesson lesson2 = modelFactory.createLesson();
        lesson2.setDescription(LESSON_2_DESC);
        lesson2.setStart(createDate(2018, 10, 3, 11, 2));
        lesson2.setEnd(createDate(2018, 10, 3, 12, 2));

        ILesson lesson3 = modelFactory.createLesson();
        lesson3.setDescription(LESSON_3_DESC);
        lesson3.setStart(createDate(2018, 10, 4, 11, 3));
        lesson3.setEnd(createDate(2018, 10, 4, 12, 3));

        ILesson lesson4 = modelFactory.createLesson();
        lesson4.setDescription(LESSON_4_DESC);
        lesson4.setStart(createDate(2018, 10, 5, 11, 4));
        lesson4.setEnd(createDate(2018, 10, 5, 12, 4));

        ILesson lesson5 = modelFactory.createLesson();
        lesson5.setDescription(LESSON_5_DESC);
        lesson5.setStart(createDate(2018, 12, 1, 11, 5));
        lesson5.setEnd(createDate(2018, 12, 0, 12, 5));

        lesson1.addLecturer(lecturer1);
        lecturer1.addLesson(lesson1);
        lesson1.addLecturer(lecturer2);
        lecturer2.addLesson(lesson1);
        lesson2.addLecturer(lecturer2);
        lecturer2.addLesson(lesson2);
        lesson3.addLecturer(lecturer3);
        lecturer3.addLesson(lesson3);
        lesson4.addLecturer(lecturer1);
        lecturer1.addLesson(lesson4);
        lesson5.addLecturer(lecturer2);
        lecturer2.addLesson(lesson5);

        lesson1.addRequiredByLesson(lesson2);
        lesson1.addRequiredByLesson(lesson3);
        lesson2.addRequiredLesson(lesson1);
        lesson3.addRequiredLesson(lesson1);
        lesson2.addRequiredByLesson(lesson4);
        lesson3.addRequiredByLesson(lesson4);
        lesson4.addRequiredLesson(lesson2);
        lesson4.addRequiredLesson(lesson3);

        lesson1.setCourse(course1);
        lesson2.setCourse(course1);
        lesson3.setCourse(course1);
        lesson4.setCourse(course1);
        course1.addLesson(lesson1);
        course1.addLesson(lesson2);
        course1.addLesson(lesson3);
        course1.addLesson(lesson4);
        lesson5.setCourse(course2);
        course2.addLesson(lesson5);

        lesson1.addMaterial(material1);
        material1.setLesson(lesson1);
        lesson2.addMaterial(material2);
        material2.setLesson(lesson2);
        lesson3.addMaterial(material3);
        material3.setLesson(lesson3);
        lesson3.addMaterial(material4);
        material4.setLesson(lesson3);
        lesson3.addMaterial(material5);
        material5.setLesson(lesson3);

        // Persist all the things!
        em.persist(lecturer1);
        em.persist(lecturer2);
        em.persist(lecturer3);
        em.persist(participant1);
        em.persist(participant2);
        em.persist(lesson1);
        em.persist(lesson2);
        em.persist(lesson3);
        em.persist(lesson4);
        em.persist(lesson5);
        em.persist(coursePlatform1);
        em.persist(coursePlatform2);
        em.persist(metadata1);
        em.persist(metadata2);
        em.persist(metadata3);
        em.persist(metadata4);
        em.persist(material1);
        em.persist(material2);
        em.persist(material3);
        em.persist(material4);
        em.persist(material5);
        em.persist(materialServer1);
        em.persist(materialServer2);
        em.persist(materialServer3);
        em.persist(course1);
        em.persist(course2);
        em.persist(course3);
        em.persist(course4);
        em.persist(enrollment1);
        em.persist(enrollment2);
        em.persist(membership1);
        em.persist(membership2);
        em.persist(membership3);

        lecturer1Id = lecturer1.getId();
        lecturer2Id = lecturer2.getId();
        lecturer3Id = lecturer3.getId();
        participant1Id = participant1.getId();
        participant2Id = participant2.getId();
        membership1Id = membership1.getId();
        membership2Id = membership2.getId();
        membership3Id = membership3.getId();
        lesson1Id = lesson1.getId();
        lesson2Id = lesson2.getId();
        lesson3Id = lesson3.getId();
        lesson4Id = lesson4.getId();
        lesson5Id = lesson5.getId();
        coursePlatform1Id = coursePlatform1.getId();
        coursePlatform2Id = coursePlatform2.getId();
        metadata1Id = metadata1.getId();
        metadata2Id = metadata2.getId();
        material1Id = material1.getId();
        material2Id = material2.getId();
        material3Id = material3.getId();
        material4Id = material4.getId();
        material5Id = material5.getId();
        materialServer1Id = materialServer1.getId();
        materialServer2Id = materialServer2.getId();
        materialServer3Id = materialServer3.getId();
        course1Id = course1.getId();
        course2Id = course2.getId();
        course3Id = course3.getId();
        course4Id = course3.getId();

        em.flush();
    }

    private MessageDigest getMessageDigest() {
        try {
            return MessageDigest.getInstance("SHA1");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException(e);
        }
    }

}
