package page.example.school;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.StringTokenizer;

import org.wikiwebserver.handler.http.HTTPException;
import org.wikiwebserver.handler.http.interfaces.HTTPResponder;
import page.config.SiteTemplatedPage;

import static org.wikiwebserver.html.HTMLHelper.*;



public class Generator2 extends SiteTemplatedPage implements HTTPResponder, ReportGenerator {
	
    public void generate() throws HTTPException {
        
        setTitle("Report Generator - WikiWebServer.org");
        
        String name = "[NAME]";
        String module = "[MODULE]";
        String course = "[COURSE]";
        Performance social = Performance.AVERAGE;
        Performance book = Performance.AVERAGE;
        Performance home = Performance.AVERAGE;
        Performance practical = Performance.AVERAGE;
        Performance effort = Performance.AVERAGE;
        String grade = "B";
        String mockGrade = "B";
        String targetGrade = "B";
        
        if (getFormData() != null) {
            name = getFormData().getFirst("name");
            module = getFormData().getFirst("module");
            course = getFormData().getFirst("course");
            social = Performance.getPerformance(getFormData().getFirst("social"));
            book = Performance.getPerformance(getFormData().getFirst("book"));
            home = Performance.getPerformance(getFormData().getFirst("home"));
            practical = Performance.getPerformance(getFormData().getFirst("practical"));
            effort = Performance.getPerformance(getFormData().getFirst("effort"));
            grade = getFormData().getFirst("grade");
            mockGrade = getFormData().getFirst("mockgrade");
            targetGrade = getFormData().getFirst("targetgrade");
        }
        

        append(h(1, "Report Generator"));
        
        append(form(
                  p("Name: " + textfield("name", name) +
                   " Course: " + textfield("course", course) + 
                   " Module: " + textfield("module", module) + br() +
                   " Average Grade: " + getGradeSelect("grade", grade) +               
                   " Mock Grade: " + getGradeSelect("mockgrade", mockGrade) +       
                   " Target Grade: " + getGradeSelect("targetgrade", targetGrade) +  br() +                 
                   " Social: " + getPerformanceSelect("social", social) +
                   " Book: " + getPerformanceSelect("book", book) +
                   " Homework: " + getPerformanceSelect("home", home) +
                   " Practical: " + getPerformanceSelect("practical", practical) +
                   " Effort: " + getPerformanceSelect("effort", effort) + br() +
                   
                   submitbutton("action", "Generate"))));
        
        
        String report = getReport(name, course, module, grade, mockGrade, targetGrade, social, book, home, practical, effort);
        
        append(textarea("report", report, "style='font-size: 1.3em; width: 100%' rows='15'"));
        append(p("Characters: " + report.length()));
        
    }  
    
    public String getReport(String... data) {
        
        if (data.length == 1) {
            StringTokenizer tokenizer = new StringTokenizer(data[0], "\t");
            
            LinkedList<String> columns = new LinkedList<String>();
            while (tokenizer.hasMoreTokens()) {
                columns.add(tokenizer.nextToken());
            }
            
            data = columns.toArray(new String[columns.size()]);
        }
        
        if (data.length < 10) {
            throw new IllegalArgumentException("Empty field or not enough columns in source data (" + data.length + ")");
        }
        
        int idx = 0;
        String name = data[idx++].trim();
        String course = data[idx++].trim();
        String module = null;
        if (data.length == 11) module = data[idx++];
        String grade = data[idx++];
        String mockGrade = data[idx++];
        String targetGrade = data[idx++];
        Performance social = Performance.getPerformance(data[idx++]);
        Performance bookwork = Performance.getPerformance(data[idx++]);
        Performance homework = Performance.getPerformance(data[idx++]);
        Performance practical = Performance.getPerformance(data[idx++]);
        Performance effort = Performance.getPerformance(data[idx++]);
        
        return getReport(name, course, module, grade, mockGrade, targetGrade, social, bookwork, homework, practical, effort);
    }
    
    public String getReport(String name, 
                                   String course, 
                                   String module, 
                                   String grade,
                                   String mockGrade,
                                   String targetGrade,
                                   Performance social,
                                   Performance book,
                                   Performance home,
                                   Performance practical,
                                   Performance effort) {
        
        grade = grade.toUpperCase();
        
        StringBuilder rep = new StringBuilder();
        rep.append("This year we have completed the Core " + course + " GCSE course. ");
                
        //" This module investigates the work of food science professionals" +
        //" and the application of science to these professions. ");
        
        rep.append(name);
        rep.append(" is a ");
        
        // Social variation
        if (social == Performance.GOOD) rep.append("friendly and popular");
        else if (social == Performance.AVERAGE) rep.append("friendly");
        else if (social == Performance.POOR) rep.append("quiet");
        rep.append(" member of the class who ");
        if (social == Performance.GOOD) rep.append("contributes very well to");
        else if (social == Performance.AVERAGE) rep.append("contributes well to");
        else if (social == Performance.POOR) rep.append("could contribute further to");
        rep.append(" class discussions. ");
        
        rep.append(name);
        rep.append("'s book work is of ");
        if (book == Performance.GOOD) rep.append("a good"); 
        else if (book == Performance.AVERAGE) rep.append("a satisfactory"); 
        else if (book == Performance.POOR) rep.append("a poor");
        rep.append(" standard");
        
        if ((book == Performance.GOOD && home == Performance.POOR) ||
            (book == Performance.POOR && home == Performance.GOOD)) {
            rep.append(" but");
        }
        else rep.append(" and");
        
        
        if (home == Performance.GOOD) rep.append(" all of the");
        else if (home == Performance.AVERAGE) rep.append(" most of the");
        else if (home == Performance.POOR) rep.append(" very little of the");
        rep.append(" homework has been completed. ");
        
        rep.append(name);
        rep.append(" works ");
        if (practical == Performance.GOOD) rep.append("carefully and safely");
        else if (practical == Performance.AVERAGE) rep.append("quite well");
        else if (practical == Performance.POOR) rep.append("with little care and attention");
        rep.append(" during practical work to collect suitable data. ");
        
        if (effort == Performance.GOOD) {
            rep.append(name + " performs well in class, is motivated and works " +
                       "at a good pace. ");
        }
        else if (effort == Performance.AVERAGE) {
            rep.append("Unfortunately " + name + " sometimes lacks motivation " +
            "in class and can be distracted, slowing her pace of work. ");
        }
        else if (effort == Performance.POOR) {
            rep.append("Unfortunately " + name + " lacks motivation " +
            "in class and distracts others making her pace of work slow. ");
        }
        
        rep.append("In the module tests, " + name + " averaged ");
        
        /*
        if (grade.charAt(0) >= 'E') rep.append("a very disappointing");
        else if (grade.charAt(0) >= 'D') rep.append("a disappointing");
        else if (grade.charAt(0) >= 'C') rep.append("a satisfactory");
        else if (grade.charAt(0) >= 'B') rep.append("a good");
        else if (grade.charAt(0) >= 'A') rep.append("an excellent");
        else if (grade.equals("A*")) rep.append("a fantastic");
        rep.append(" grade " + grade);
        */
        
        rep.append("a grade " + grade + " and achieved ");
        
        /*
        if (mockGrade.charAt(0) >= 'E') rep.append("a very disappointing");
        else if (mockGrade.charAt(0) >= 'D') rep.append("a disappointing");
        else if (mockGrade.charAt(0) >= 'C') rep.append("a satisfactory");
        else if (mockGrade.charAt(0) >= 'B') rep.append("a good");
        else if (mockGrade.charAt(0) >= 'A') rep.append("an excellent");
        else if (mockGrade.equals("A*")) rep.append("a fantastic");
        */
        
        if (mockGrade.charAt(0) == 'A' || mockGrade.charAt(0) == 'E') {
            rep.append("an");        
        } 
        else {
            rep.append("a");
        }        
        
        rep.append(" " + mockGrade + " in her mock exam. ");        
        
        rep.append("I am hopeful this performance has been ");
        
        if (targetGrade.charAt(0) < mockGrade.charAt(0)) {
            rep.append("improved");
        }
        else {
            rep.append("repeated");
        }    
        
        rep.append(" for the actual exam to ");
        
        if (targetGrade.charAt(0) > mockGrade.charAt(0)) {
            rep.append("exceed");
        }
        else {
            rep.append("meet");
        }                    
        
        rep.append(" her target of ");
        
        if (targetGrade.charAt(0) == 'A' || targetGrade.charAt(0) == 'E') {
            rep.append("an");        
        } 
        else {
            rep.append("a");
        }
        
        rep.append(" " + targetGrade + ".");
        
        return rep.toString();
    }
    
    
    
    private String getPerformanceSelect(String name, Performance current) {
        
        String selected = current == null ? null : current.getLabel();
        Collection<String> perf = new ArrayList<String>();
        for (Performance p: Performance.values()) {
            perf.add(p.getLabel());
        }
        return select(name, perf, selected);
    }
    
    private String getGradeSelect(String name, String selected) {
        
        Collection<String> grade = new ArrayList<String>();
        grade.add("A*");
        for (char c = 'A'; c<='E'; c++) {
            grade.add(String.valueOf(c));
        }
        grade.add("U");
        return select(name, grade, selected);
    }    
    
    
    private enum Performance { 
        GOOD("A"), 
        AVERAGE("B"), 
        POOR("C");
        
        private String label;
        
        private Performance(String label) {
            this.label = label;
        }
        
        private String getLabel() {
            return label;
        }
        
        public static Performance getPerformance(String label) {
            label = label.trim();
            for (Performance p : Performance.values()) {
                if (p.getLabel().equalsIgnoreCase(label)) {
                    return p;
                }
            }
            throw new IllegalArgumentException("Bad performance rating, expected A-C");
        }
    };    
}
