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

import java.util.Collection;
import java.util.List;

import net.sourceforge.fenixedu.domain.StudentCurricularPlan;
import net.sourceforge.fenixedu.domain.student.Registration;
import net.sourceforge.fenixedu.domain.student.Student;
import net.sourceforge.fenixedu.domain.studentCurriculum.CurriculumGroup;
import net.sourceforge.fenixedu.domain.studentCurriculum.CurriculumModule;
import net.sourceforge.fenixedu.domain.studentCurriculum.ExtraCurriculumGroup;
import pt.utl.ist.scripts.commons.AtomicScript;
import pt.utl.ist.scripts.dataTransferObject.IFileLine;
import pt.utl.ist.scripts.utils.DataLoaderFromFile;

public class UpdateSpecialSeasonState extends AtomicScript {

    @Override
    protected void run() throws Exception {
        final Collection<FlunkedStudent> flunkedStudents =
                new DataLoaderFromFile().load(FlunkedStudent.class, IMPORT_DIR_PATH + "/alunosSpecialSeason.csv");
        for (FlunkedStudent flunkedStudent : flunkedStudents) {
            Student student = Student.readStudentByNumber(Integer.valueOf(flunkedStudent.getStudentNumber()));
            if (student == null) {
                logger.info("Can't find student -> " + flunkedStudent.getStudentNumber());
                continue;
            }

            processStudent(student);
        }

    }

    private void processStudent(Student student) {
        logger.info("Process Student -> " + student.getNumber());
        List<Registration> transitionRegistrations = student.getTransitionRegistrations();
        if (!transitionRegistrations.isEmpty()) {
            for (Registration registration : transitionRegistrations) {
                deleteRegistration(registration);
            }
        }
        logger.info("*************************************");
    }

    private void deleteRegistration(Registration registration) {
        logger.info("Delete Transitions Registration For " + registration.getDegree().getName());
        if (registration == null || !registration.isTransition()) {
            throw new RuntimeException("error.trying.to.delete.invalid.registration");
        }

        for (; registration.hasAnyStudentCurricularPlans();) {
            final StudentCurricularPlan studentCurricularPlan = registration.getStudentCurricularPlans().iterator().next();
            if (!studentCurricularPlan.isBolonhaDegree()) {
                throw new RuntimeException("What?");
            }

            deleteCurriculumModules(studentCurricularPlan.getRoot());
            removeEmptyGroups(studentCurricularPlan.getRoot());

            final ExtraCurriculumGroup extraCurriculumGroup = studentCurricularPlan.getExtraCurriculumGroup();
            if (extraCurriculumGroup != null) {
                extraCurriculumGroup.deleteRecursive();
            }
            if (studentCurricularPlan.hasRoot()) {
                studentCurricularPlan.getRoot().delete();
            }
            studentCurricularPlan.delete();
        }

        registration.delete();

    }

    protected void deleteCurriculumModules(final CurriculumModule curriculumModule) {

        if (curriculumModule == null) {
            return;
        }

        if (!curriculumModule.isLeaf()) {
            final CurriculumGroup curriculumGroup = (CurriculumGroup) curriculumModule;
            for (final CurriculumModule each : curriculumGroup.getCurriculumModules()) {
                deleteCurriculumModules(each);
            }
        } else if (curriculumModule.isDismissal()) {
            curriculumModule.delete();
        } else {
            throw new RuntimeException("error.in.transition.state.can.only.remove.groups.and.dismissals");
        }
    }

    protected void removeEmptyGroups(final CurriculumGroup curriculumGroup) {

        if (curriculumGroup == null) {
            return;
        }

        for (final CurriculumModule curriculumModule : curriculumGroup.getCurriculumModules()) {
            if (!curriculumModule.isLeaf()) {
                removeEmptyChildGroups((CurriculumGroup) curriculumModule);
            }
        }
    }

    private void removeEmptyChildGroups(final CurriculumGroup curriculumGroup) {

        for (final CurriculumModule curriculumModule : curriculumGroup.getCurriculumModules()) {
            if (!curriculumModule.isLeaf()) {
                removeEmptyChildGroups((CurriculumGroup) curriculumModule);
            }
        }

        if (!curriculumGroup.hasAnyCurriculumModules() && !curriculumGroup.isRoot() && !curriculumGroup.isExtraCurriculum()) {
            curriculumGroup.deleteRecursive();
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        processWriteTransaction(new UpdateSpecialSeasonState());
        System.exit(0);
    }

    public static class FlunkedStudent implements IFileLine {

        public Integer studentNumber;

        private final String LINE_SEPARATOR = "\t";

        @Override
        public boolean fillWithFileLineData(String dataLine) {
            String[] line = dataLine.split(LINE_SEPARATOR);

            if (line.length < 1) {
                System.out.println("Invalid line, ignoring it.");
                return false;
            }

            studentNumber = Integer.valueOf(line[0].trim());

            return true;
        }

        @Override
        public String getUniqueKey() {
            // TODO Auto-generated method stub
            return null;
        }

        public Integer getStudentNumber() {
            return studentNumber;
        }

        public void setStudentNumber(Integer studentNumber) {
            this.studentNumber = studentNumber;
        }
    }

}
