package pt.utl.ist.scripts.runOnce;

import java.util.Collections;
import java.util.Comparator;
import java.util.Set;

import net.sourceforge.fenixedu.domain.Employee;
import net.sourceforge.fenixedu.domain.ExecutionYear;
import net.sourceforge.fenixedu.domain.Person;
import net.sourceforge.fenixedu.domain.StudentCurricularPlan;
import net.sourceforge.fenixedu.domain.Teacher;
import net.sourceforge.fenixedu.domain.cardGeneration.CardGenerationBatch;
import net.sourceforge.fenixedu.domain.cardGeneration.CardGenerationEntry;
import net.sourceforge.fenixedu.domain.degree.DegreeType;
import net.sourceforge.fenixedu.domain.student.Student;

import org.joda.time.DateTime;
import org.joda.time.YearMonthDay;

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

public class CreateNewCardEntries extends AtomicScript {

    @Override
    protected void run() throws Exception {
        try {
            CardGenerationBatch cardGenerationBatch = findBatch("Conjunto 19");
            if (cardGenerationBatch == null) {
                cardGenerationBatch = new CardGenerationBatch("Conjunto 19", ExecutionYear.readCurrentExecutionYear(), true);
            }
            System.out.println("Processing: " + cardGenerationBatch.getDescription() + " "
                    + cardGenerationBatch.getExecutionYear().getYear());

            createEntries(cardGenerationBatch);
        } finally {
            System.out.println("Done.");
            System.out.flush();
            System.err.flush();
        }
    }

    private CardGenerationBatch findBatch(final String batchName) {
        for (final CardGenerationBatch cardGenerationBatch : rootDomainObject.getCardGenerationBatchesSet()) {
            if (cardGenerationBatch.getDescription().equals(batchName)) {
                return cardGenerationBatch;
            }
        }
        return null;
    }

    private StudentCurricularPlan findStudentCurricularPlan(final CardGenerationBatch cardGenerationBatch, final Student student,
            final DateTime begin, final DateTime end) {
        final Set<StudentCurricularPlan> studentCurricularPlans =
                cardGenerationBatch.getStudentCurricularPlans(begin, end, student);
        if (studentCurricularPlans.size() == 1) {
            return studentCurricularPlans.iterator().next();
        } else if (studentCurricularPlans.size() > 1) {
            final StudentCurricularPlan max = findMaxStudentCurricularPlan(studentCurricularPlans);
            return max;
        }
        return null;
    }

    private StudentCurricularPlan findMaxStudentCurricularPlan(final Set<StudentCurricularPlan> studentCurricularPlans) {
        return Collections.max(studentCurricularPlans, new Comparator<StudentCurricularPlan>() {

            @Override
            public int compare(final StudentCurricularPlan o1, final StudentCurricularPlan o2) {
                final DegreeType degreeType1 = o1.getDegreeType();
                final DegreeType degreeType2 = o2.getDegreeType();
                if (degreeType1 == degreeType2) {
                    final YearMonthDay yearMonthDay1 = o1.getStartDateYearMonthDay();
                    final YearMonthDay yearMonthDay2 = o2.getStartDateYearMonthDay();
                    final int c = yearMonthDay1.compareTo(yearMonthDay2);
                    return c == 0 ? o1.getExternalId().compareTo(o2.getExternalId()) : c;
                } else {
                    return degreeType1.compareTo(degreeType2);
                }
            }

        });
    }

    private void createEntries(final CardGenerationBatch cardGenerationBatch) {
        final ExecutionYear executionYear = cardGenerationBatch.getExecutionYear();
        final DateTime begin = executionYear.getBeginDateYearMonthDay().toDateTimeAtMidnight();
        final DateTime end = executionYear.getEndDateYearMonthDay().toDateTimeAtMidnight();;

        int ok = 0, u = 0, c = 500, i = 0;
        for (final Student student : rootDomainObject.getStudentsSet()) {
            if (--c == 0) {
                System.out.println("Processed: " + ((i + 1) * 500) + " students.");
                c = 500;
                i++;
            }

            final Person person = student.getPerson();

            if (person == null || person.hasAnyCardGenerationEntries()) {
                continue;
            }

            final Teacher teacher = person.getTeacher();
            final Employee employee = person.getEmployee();

            if ((teacher == null || !teacher.isActive()) && (employee == null || !employee.isActive())
                    && !student.getActiveRegistrations().isEmpty()) {
                final StudentCurricularPlan studentCurricularPlan =
                        findStudentCurricularPlan(cardGenerationBatch, student, begin, end);
                if (studentCurricularPlan != null) {
                    final CardGenerationEntry cardGenerationEntry = new CardGenerationEntry();
                    cardGenerationEntry.setCreated(new DateTime());
                    cardGenerationEntry.setCardGenerationBatch(cardGenerationBatch);
                    cardGenerationEntry.setPerson(person);
                    cardGenerationEntry.setLine(studentCurricularPlan);

                    ok++;
                } else {
                    u++;
                }

            }
        }

        System.out.println("Ok     : " + ok);
        System.out.println("unknown: " + u);
    }

    public static void main(final String[] args) {
        processWriteTransaction(new CreateNewCardEntries());
        System.exit(0);
    }

}
