package pt.utl.ist.scripts.process.updateData;

import java.util.HashSet;
import java.util.Set;

import net.sourceforge.fenixedu.domain.Attends;
import net.sourceforge.fenixedu.domain.CurricularCourse;
import net.sourceforge.fenixedu.domain.Enrolment;
import net.sourceforge.fenixedu.domain.ExecutionCourse;
import net.sourceforge.fenixedu.domain.ExecutionSemester;
import net.sourceforge.fenixedu.domain.ExecutionYear;
import net.sourceforge.fenixedu.domain.student.Registration;
import pt.ist.fenixframework.FenixFramework;
import pt.utl.ist.scripts.commons.AtomicScript;

public class CreateMissingAttends extends AtomicScript {

    @Override
    protected void run() throws Exception {
    }

    private static final Set<String> enrolmentIds = new HashSet<String>();

    private static class EnrolmentFinder extends AtomicProcedure {

        @Override
        public void proc() throws Exception {
            final ExecutionYear executionYear =
                    ExecutionYear.readCurrentExecutionYear().getPreviousExecutionYear().getPreviousExecutionYear()
                            .getPreviousExecutionYear();
            for (final ExecutionSemester executionSemester : executionYear.getExecutionPeriodsSet()) {
                for (final Enrolment enrolment : executionSemester.getEnrolmentsSet()) {
                    if (enrolment.getCurricularCourse().isAnual()) {
                        if (enrolment.getAttendsSet().size() < 2) {
                            enrolmentIds.add(enrolment.getExternalId());
                        }
                    } else {
                        if (!enrolment.hasAnyAttends()) {
                            enrolmentIds.add(enrolment.getExternalId());
                        }
                    }
                }
            }
        }

    }

    private static class FixEnrolment extends AtomicProcedure {

        private final String enrolmentId;

        public FixEnrolment(final String enrolmentId) {
            this.enrolmentId = enrolmentId;
        }

        @Override
        public void proc() throws Exception {
            final Enrolment enrolment = FenixFramework.getDomainObject(enrolmentId);
            final ExecutionSemester executionSemester = enrolment.getExecutionPeriod();
            if (enrolment.getCurricularCourse().isAnual()) {
                if (executionSemester.getSemester().intValue() == 1) {
                    final ExecutionYear executionYear = enrolment.getExecutionYear();
                    for (final ExecutionSemester executionSemester2 : executionYear.getExecutionPeriodsSet()) {
                        process(enrolment, executionSemester2);
                    }
                }
            } else {
                process(enrolment, enrolment.getExecutionPeriod());
            }
        }

        private void process(final Enrolment enrolment, final ExecutionSemester executionSemester) {
            if (!enrolment.hasAttendsFor(executionSemester)) {
                final CurricularCourse curricularCourse = enrolment.getCurricularCourse();
                final ExecutionCourse executionCourse = findExecutionCourse(curricularCourse, executionSemester);
                if (executionCourse != null) {
                    final Registration registration = enrolment.getRegistration();
                    final Attends attends = findAttends(executionCourse, registration);
                    if (attends == null) {
                        System.out.println("Creating attends for " + registration.getNumber() + " " + executionCourse.getNome());
                        new Attends(registration, executionCourse);
                    } else {
                        if (attends.getEnrolment() == null) {
                            System.out.println("Connecting attends for " + registration.getNumber() + " "
                                    + executionCourse.getNome());
                            attends.setEnrolment(enrolment);
                        }
                    }
                }
            }
        }

        private Attends findAttends(final ExecutionCourse executionCourse, final Registration registration) {
            for (final Attends attends : executionCourse.getAttendsSet()) {
                if (attends.getRegistration() == registration) {
                    return attends;
                }
            }
            return null;
        }

        private ExecutionCourse findExecutionCourse(final CurricularCourse curricularCourse,
                final ExecutionSemester executionSemester) {
            for (final ExecutionCourse executionCourse : curricularCourse.getExecutionCoursesByExecutionPeriod(executionSemester)) {
                return executionCourse;
            }
            return null;
        }

    }

    public static void main(String[] args) {
        doAction(new EnrolmentFinder());
        System.out.println("Need to process " + enrolmentIds.size() + " enrolments.");

        for (final String enrolmentId : enrolmentIds) {
            doAction(new FixEnrolment(enrolmentId));
        }

        System.exit(0);
    }

}
