package pt.utl.ist.scripts.runOnce;

import net.sourceforge.fenixedu.dataTransferObject.CurricularPeriodInfoDTO;
import net.sourceforge.fenixedu.domain.CurricularCourse;
import net.sourceforge.fenixedu.domain.DegreeCurricularPlan;
import net.sourceforge.fenixedu.domain.Enrolment;
import net.sourceforge.fenixedu.domain.ExecutionSemester;
import net.sourceforge.fenixedu.domain.StudentCurricularPlan;
import net.sourceforge.fenixedu.domain.curricularPeriod.CurricularPeriod;
import net.sourceforge.fenixedu.domain.curriculum.EnrollmentCondition;
import net.sourceforge.fenixedu.domain.degreeStructure.Context;
import net.sourceforge.fenixedu.domain.student.Registration;
import net.sourceforge.fenixedu.domain.studentCurriculum.CurriculumGroup;
import net.sourceforge.fenixedu.domain.studentCurriculum.CurriculumModule;
import net.sourceforge.fenixedu.domain.time.calendarStructure.AcademicPeriod;

import org.joda.time.YearMonthDay;

import pt.utl.ist.scripts.commons.AtomicScript;

public class CreateFirstTimeStudentCurricularPlansForBolonha extends AtomicScript {

    public static void main(String[] args) {
        process(new CreateFirstTimeStudentCurricularPlansForBolonha());
        System.exit(0);
    }

    @Override
    protected void run() throws Exception {

        

        final ExecutionSemester executionPeriod = ExecutionSemester.readActualExecutionSemester();

        // Create StudentCurricularPlan
        // -------------------------------------------------------------
        final DegreeCurricularPlan degreeCurricularPlan = DegreeCurricularPlan.readByNameAndDegreeSigla("MEE 2006", "MEE");
        final Registration registration = Registration.readByUsername("L50000");
        final StudentCurricularPlan studentCurricularPlan =
                StudentCurricularPlan.createBolonhaStudentCurricularPlan(registration, degreeCurricularPlan, new YearMonthDay(),
                        executionPeriod);

        // ------------------------------------------------------------------------------------------

        final CurricularPeriod curricularPeriod = getCurricularPeriodFor(studentCurricularPlan.getDegreeCurricularPlan(), 1, 1);
        createFirstTimeStudentEnrolmentsFor(studentCurricularPlan, curricularPeriod, executionPeriod, "CREATED_BY");

        logger.info(studentCurricularPlan.getRoot().print("").toString());

        // TODO: abort transaction
        throw new Error();

    }

    private void createFirstTimeStudentEnrolmentsFor(StudentCurricularPlan studentCurricularPlan,
            CurricularPeriod curricularPeriod, ExecutionSemester executionPeriod, String createdBy) {
        createFirstTimeStudentEnrolmentsFor(studentCurricularPlan, studentCurricularPlan.getRoot(), curricularPeriod,
                executionPeriod, createdBy);
    }

    private void createFirstTimeStudentEnrolmentsFor(StudentCurricularPlan studentCurricularPlan,
            CurriculumGroup curriculumGroup, CurricularPeriod curricularPeriod, ExecutionSemester executionPeriod,
            String createdBy) {

        for (final Context context : curriculumGroup.getDegreeModule().getContextsWithCurricularCourseByCurricularPeriod(
                curricularPeriod, executionPeriod)) {
            new Enrolment(studentCurricularPlan, curriculumGroup, (CurricularCourse) context.getChildDegreeModule(),
                    executionPeriod, EnrollmentCondition.FINAL, createdBy);
        }

        for (final CurriculumModule curriculumModule : curriculumGroup.getCurriculumModulesSet()) {
            if (!curriculumModule.isLeaf()) {
                createFirstTimeStudentEnrolmentsFor(studentCurricularPlan, (CurriculumGroup) curriculumModule, curricularPeriod,
                        executionPeriod, createdBy);
            }
        }
    }

    // TODO: check this method
    private CurricularPeriod getCurricularPeriodFor(DegreeCurricularPlan curricularPlan, int year, int semester) {

        final CurricularPeriodInfoDTO[] curricularPeriodInfos;
        if (curricularPlan.getDegree().getDegreeType().getYears() > 1) {

            curricularPeriodInfos =
                    new CurricularPeriodInfoDTO[] { new CurricularPeriodInfoDTO(year, AcademicPeriod.YEAR),
                            new CurricularPeriodInfoDTO(semester, AcademicPeriod.SEMESTER) };

        } else {
            curricularPeriodInfos =
                    new CurricularPeriodInfoDTO[] { new CurricularPeriodInfoDTO(semester, AcademicPeriod.SEMESTER) };
        }

        return curricularPlan.getDegreeStructure().getCurricularPeriod(curricularPeriodInfos);
    }
}
