package dynamic.degrees;

import dynamic.common.ContentGrabber;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

public class DegreeHtmlFormatter {

    public static String LEVEL1O = "<h2>";
    public static String LEVEL1C = "</h2>";
    public static String LEVEL2O = "<h3>";
    public static String LEVEL2C = "</h3>";

    private static BufferedWriter f;

    public static String link_stub = "/computing/teaching/courses/";

    public static void FormatOutput(String fname, String degree_code) throws IOException {

//        String title = DegreeInfoGetter.GetDegreeTitle(degree_code);
        ArrayList<Integer> years = DegreeInfoGetter.GetDegreeYears(degree_code);
        String format_order = DegreeIniHandler.GetFormatOrder(degree_code);

        f = new BufferedWriter(new FileWriter(fname));

        // header and supplementary information if present
        f.write(ContentGrabber.content_div_tag_open);

//        // OLD CODE FOR GENERATING PAGE INTRODUCTIONS AND TITLES
//        f.write("<h1>" + title + "</h1>");
//
//        String supp_info = DegreeIniHandler.GetSupplementaryInfo(degree_code);
//        if(supp_info.length() > 0)
//            f.write("<p>" + supp_info + "</p>");

        if (years.size() == 1) // one year postgrad degree
            if(format_order.equals("term_opt"))
                CreateCoursesListByTermThenCompulsion(degree_code, years.get(0));
            else if(format_order.equals("opt_term"))
                CreateCoursesListByCompulsionThenTerm(degree_code, years.get(0));
            else
                CreateCoursesListByTermThenCompulsion(degree_code, years.get(0));
        else {

            int todo = years.size();

            while (todo > 0) {

                if (todo >= 2)
                    CreateTwoColumnBlock(degree_code, years.get(years.size() - todo), years.get(years.size() - todo + 1));
                else
                    CreateTwoColumnBlock(degree_code, years.get(years.size() - todo), 0);

                todo -= 2;

            }
        }
        f.write(ContentGrabber.content_div_tag_close);

        f.close();

    }

    private static void CreateTwoColumnBlock(String degree_code, int year1, int year2) throws IOException {

        f.write("<div class=\"column-wrapper\">");
        f.write("<div class=\"two-col-block\">");
        f.write("<div class=\"col\">");


        if (year1 != 0){
            f.write("<h2>Year " + year1 + "</h2>");
            CreateCoursesList(degree_code, year1);
        }

        f.write("</div>");
        f.write("<div class=\"col\">");

        if (year2 != 0){
            f.write("<h2>Year " + year2 + "</h2>");
            CreateCoursesList(degree_code, year2);
        }


        f.write("</div>");
        f.write("<div class=\"clear\"></div>");
        f.write("</div>");
        f.write("</div>");


    }

    private static void CreateCoursesListByCompulsionThenTerm(String degree_code, int year) throws IOException {

        ArrayList<ArrayList<String>> courses = DegreeInfoGetter.GetCompulsoryCourses(degree_code, year);
        CreateCourseListForCompulsionWithTranslatedTitleByTerm("Compulsory",degree_code,year,courses);

        courses = DegreeInfoGetter.GetSelectiveCourses(degree_code, year);
        CreateCourseListForCompulsionWithTranslatedTitleByTerm("Selective",degree_code,year,courses);

        courses = DegreeInfoGetter.GetSelective1Courses(degree_code, year);
        CreateCourseListForCompulsionWithTranslatedTitleByTerm("Selective1",degree_code,year,courses);

        courses = DegreeInfoGetter.GetSelective2Courses(degree_code, year);
        CreateCourseListForCompulsionWithTranslatedTitleByTerm("Selective2",degree_code,year,courses);

        courses = DegreeInfoGetter.GetSelective3Courses(degree_code, year);
        CreateCourseListForCompulsionWithTranslatedTitleByTerm("Selective3",degree_code,year,courses);

        courses = DegreeInfoGetter.GetOptionalCourses(degree_code, year);
        CreateCourseListForCompulsionWithTranslatedTitleByTerm("Optional",degree_code,year,courses);

        courses = DegreeInfoGetter.GetOptional1Courses(degree_code, year);
        CreateCourseListForCompulsionWithTranslatedTitleByTerm("Optional1",degree_code,year,courses);

        courses = DegreeInfoGetter.GetOptional2Courses(degree_code, year);
        CreateCourseListForCompulsionWithTranslatedTitleByTerm("Optional2",degree_code,year,courses);

        courses = DegreeInfoGetter.GetOptional3Courses(degree_code, year);
        CreateCourseListForCompulsionWithTranslatedTitleByTerm("Optional3",degree_code,year,courses);

    }

    private static void CreateCourseListForCompulsionWithTranslatedTitleByTerm(String category, String degree_code, int year, ArrayList<ArrayList<String>> courses) throws IOException {

        if (courses.isEmpty())
            return;

        SimplifyTermNames(courses);

        String title = DegreeIniHandler.GetOptionTitle(category, degree_code, year);
        f.write(LEVEL1O + title + LEVEL1C);

        String[] terms = {"Autumn","Spring","Summer"};
        for (int i = 0; i < terms.length; i++) {
            String term = terms[i];

            ArrayList<ArrayList<String>> courses_term = PullOutByTerm(courses, term);
            if(!courses_term.isEmpty()){
                f.write(LEVEL2O + term + " Term" + LEVEL2C);
                CreateCoursesUL(courses_term);
            }
        }

        while(!courses.isEmpty()){
            String term = courses.get(0).get(2);
            ArrayList<ArrayList<String>> courses_for_term = PullOutByTerm(courses, term);
            f.write(LEVEL2O + term + " Term" + LEVEL2C);
            CreateCoursesUL(courses_for_term);
        }

    }

    private static void CreateCoursesListByTermThenCompulsion(String degree_code,int year) throws IOException {

        ArrayList<ArrayList<String>> compulsory_courses = DegreeInfoGetter.GetCompulsoryCourses(degree_code, year);
        ArrayList<ArrayList<String>> selective_courses = DegreeInfoGetter.GetSelectiveCourses(degree_code, year);
        ArrayList<ArrayList<String>> selective1_courses = DegreeInfoGetter.GetSelective1Courses(degree_code, year);
        ArrayList<ArrayList<String>> selective2_courses = DegreeInfoGetter.GetSelective2Courses(degree_code, year);
        ArrayList<ArrayList<String>> selective3_courses = DegreeInfoGetter.GetSelective3Courses(degree_code, year);
        ArrayList<ArrayList<String>> optional_courses = DegreeInfoGetter.GetOptionalCourses(degree_code, year);
        ArrayList<ArrayList<String>> optional1_courses = DegreeInfoGetter.GetOptional1Courses(degree_code, year);
        ArrayList<ArrayList<String>> optional2_courses = DegreeInfoGetter.GetOptional2Courses(degree_code, year);
        ArrayList<ArrayList<String>> optional3_courses = DegreeInfoGetter.GetOptional3Courses(degree_code, year);

        SimplifyTermNames(compulsory_courses);
        SimplifyTermNames(selective_courses);
        SimplifyTermNames(selective1_courses);
        SimplifyTermNames(selective2_courses);
        SimplifyTermNames(selective3_courses);
        SimplifyTermNames(optional_courses);
        SimplifyTermNames(optional1_courses);
        SimplifyTermNames(optional2_courses);
        SimplifyTermNames(optional3_courses);

        String[] terms = {"Autumn","Spring","Summer"};

        for (int i = 0; i < terms.length; i++) {
            String term = terms[i];
            ArrayList<ArrayList<String>> compulsory_courses_term = PullOutByTerm(compulsory_courses, term);
            ArrayList<ArrayList<String>> selective_courses_term = PullOutByTerm(selective_courses, term);
            ArrayList<ArrayList<String>> selective1_courses_term = PullOutByTerm(selective1_courses, term);
            ArrayList<ArrayList<String>> selective2_courses_term = PullOutByTerm(selective2_courses, term);
            ArrayList<ArrayList<String>> selective3_courses_term = PullOutByTerm(selective3_courses, term);
            ArrayList<ArrayList<String>> optional_courses_term = PullOutByTerm(optional_courses, term);
            ArrayList<ArrayList<String>> optional1_courses_term = PullOutByTerm(optional1_courses, term);
            ArrayList<ArrayList<String>> optional2_courses_term = PullOutByTerm(optional2_courses, term);
            ArrayList<ArrayList<String>> optional3_courses_term = PullOutByTerm(optional3_courses, term);

            if(!(compulsory_courses_term.isEmpty() &&
                    optional_courses_term.isEmpty() &&
                    selective1_courses_term.isEmpty() &&
                    selective2_courses_term.isEmpty() &&
                    selective3_courses_term.isEmpty())
                    )
                f.write(LEVEL1O + term + " Term" + LEVEL1C);

            CreateCourseListWithTranslatedTitle("Compulsory",degree_code,year,compulsory_courses_term);
            CreateCourseListWithTranslatedTitle("Selective",degree_code,year,selective_courses_term);
            CreateCourseListWithTranslatedTitle("Selective1",degree_code,year,selective1_courses_term);
            CreateCourseListWithTranslatedTitle("Selective2",degree_code,year,selective2_courses_term);
            CreateCourseListWithTranslatedTitle("Selective3",degree_code,year,selective3_courses_term);
            CreateCourseListWithTranslatedTitle("Optional",degree_code,year,optional_courses_term);
            CreateCourseListWithTranslatedTitle("Optional1",degree_code,year,optional1_courses_term);
            CreateCourseListWithTranslatedTitle("Optional2",degree_code,year,optional2_courses_term);
            CreateCourseListWithTranslatedTitle("Optional3",degree_code,year,optional3_courses_term);

        }

        String term = "term";
        while(term.length() != 0){
            term = "";
            if(!compulsory_courses.isEmpty())       term = compulsory_courses.get(0).get(2);
            else if (!optional_courses.isEmpty())   term = optional_courses.get(0).get(2);
            else if (!optional1_courses.isEmpty())  term = optional1_courses.get(0).get(2);
            else if (!optional2_courses.isEmpty())  term = optional2_courses.get(0).get(2);
            else if (!optional3_courses.isEmpty())  term = optional3_courses.get(0).get(2);
            else if (!selective_courses.isEmpty())  term = selective_courses.get(0).get(2);
            else if (!selective1_courses.isEmpty()) term = selective1_courses.get(0).get(2);
            else if (!selective2_courses.isEmpty()) term = selective2_courses.get(0).get(2);
            else if (!selective3_courses.isEmpty()) term = selective3_courses.get(0).get(2);

            if(term.length() > 0) {
                f.write(LEVEL1O + term + " Term" + LEVEL1C);

                ArrayList<ArrayList<String>> compulsory_courses_term = PullOutByTerm(compulsory_courses, term);
                ArrayList<ArrayList<String>> selective_courses_term = PullOutByTerm(selective1_courses, term);
                ArrayList<ArrayList<String>> selective1_courses_term = PullOutByTerm(selective1_courses, term);
                ArrayList<ArrayList<String>> selective2_courses_term = PullOutByTerm(selective2_courses, term);
                ArrayList<ArrayList<String>> selective3_courses_term = PullOutByTerm(selective3_courses, term);
                ArrayList<ArrayList<String>> optional_courses_term = PullOutByTerm(optional_courses, term);
                ArrayList<ArrayList<String>> optional1_courses_term = PullOutByTerm(optional1_courses, term);
                ArrayList<ArrayList<String>> optional2_courses_term = PullOutByTerm(optional2_courses, term);
                ArrayList<ArrayList<String>> optional3_courses_term = PullOutByTerm(optional3_courses, term);

                CreateCourseListWithTranslatedTitle("Compulsory",degree_code,year,compulsory_courses_term);
                CreateCourseListWithTranslatedTitle("Selective",degree_code,year,selective_courses_term);
                CreateCourseListWithTranslatedTitle("Selective1",degree_code,year,selective1_courses_term);
                CreateCourseListWithTranslatedTitle("Selective2",degree_code,year,selective2_courses_term);
                CreateCourseListWithTranslatedTitle("Selective3",degree_code,year,selective3_courses_term);
                CreateCourseListWithTranslatedTitle("Optional",degree_code,year,optional_courses_term);
                CreateCourseListWithTranslatedTitle("Optional1",degree_code,year,optional1_courses_term);
                CreateCourseListWithTranslatedTitle("Optional2",degree_code,year,optional2_courses_term);
                CreateCourseListWithTranslatedTitle("Optional3",degree_code,year,optional3_courses_term);

            }
        }
    }

    private static void CreateCourseListWithTranslatedTitle(String category, String degree_code, int year, ArrayList<ArrayList<String>> courses) throws IOException {
        if(courses.isEmpty())
            return;
        String title = DegreeIniHandler.GetOptionTitle(category, degree_code, year);
        f.write(LEVEL2O + title + LEVEL2C);
        CreateCoursesUL(courses);
    }

    private static void SimplifyTermNames(ArrayList<ArrayList<String>> courses) {

        for (Iterator<ArrayList<String>> iterator = courses.iterator(); iterator.hasNext(); ) {
            ArrayList<String> course =  iterator.next();
            String term = course.get(2);
            course.remove(2);
            if(term.equals("1"))
                course.add(2,"Autumn");
            else if(term.equals("2"))
                course.add(2,"Spring");
            else if(term.equals("3"))
                course.add(2,"Summer");
            else if(term.equals("1,2"))
                course.add(2,"Autumn");
            else
                course.add(2,"Unknown Term - " + term);
        }

    }

    private static ArrayList<ArrayList<String>> PullOutByTerm(ArrayList<ArrayList<String>> courses, String term){

        ArrayList<ArrayList<String>> coursesForTerm = new ArrayList<ArrayList<String>>();

        for (int i = courses.size()-1; i >= 0 ; i--)
            if(courses.get(i).get(2).equals(term))
                coursesForTerm.add(0,courses.remove(i));

        return coursesForTerm;
    }

    private static void CreateCoursesList(String degree_code, int year) throws IOException {

        ArrayList<ArrayList<String>> courses = DegreeInfoGetter.GetCompulsoryCourses(degree_code, year);
        if (courses.size() > 0) {
            CreateCourseListWithTranslatedTitle("Compulsory",degree_code,year,courses);
        }

        courses = DegreeInfoGetter.GetSelectiveCourses(degree_code, year);
        if (courses.size() > 0) {
            CreateCourseListWithTranslatedTitle("Selective",degree_code,year,courses);
        }

        courses = DegreeInfoGetter.GetSelective1Courses(degree_code, year);
        if (courses.size() > 0) {
            CreateCourseListWithTranslatedTitle("Selective1",degree_code,year,courses);
        }

        courses = DegreeInfoGetter.GetSelective2Courses(degree_code, year);
        if (courses.size() > 0) {
            CreateCourseListWithTranslatedTitle("Selective2",degree_code,year,courses);
        }

        courses = DegreeInfoGetter.GetSelective3Courses(degree_code, year);
        if (courses.size() > 0) {
            CreateCourseListWithTranslatedTitle("Selective3",degree_code,year,courses);
        }

        courses = DegreeInfoGetter.GetOptionalCourses(degree_code, year);
        if (courses.size() > 0) {
            CreateCourseListWithTranslatedTitle("Optional",degree_code,year,courses);
        }

        courses = DegreeInfoGetter.GetOptional1Courses(degree_code, year);
        if (courses.size() > 0) {
            CreateCourseListWithTranslatedTitle("Optional1",degree_code,year,courses);
        }

        courses = DegreeInfoGetter.GetOptional2Courses(degree_code, year);
        if (courses.size() > 0) {
            CreateCourseListWithTranslatedTitle("Optional2",degree_code,year,courses);
        }

        courses = DegreeInfoGetter.GetOptional3Courses(degree_code, year);
        if (courses.size() > 0) {
            CreateCourseListWithTranslatedTitle("Optional3",degree_code,year,courses);
        }

    }

    private static void CreateCoursesUL(ArrayList<ArrayList<String>> courses) throws IOException {

        f.write("<ul class=\"link-list\">");

        for (ArrayList<String> course : courses) {

            String course_id = course.get(0);
            String course_title = course.get(1);
            String course_id_link = course_id.replaceAll("\\.", "_");  // change e.g. 120.1 to 120_1 for url

            f.write("<li>");
            f.write("<a href=\"" + link_stub + course_id_link + "\"");
            f.write(" title=\"" + course_id + " " + course_title + "\">" + course_id + " " + course_title + "</a>");
            f.write("</li>");
        }

        f.write("</ul>");

    }

}
