package org.slc.sli.view;

import org.slc.sli.entity.Assessment;
import org.slc.sli.entity.Student;

import org.slc.sli.config.ViewConfig;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ArrayList;
import org.slc.sli.config.DataPoint;
import org.slc.sli.config.DataSet;

//Hopefully there will be one for each of dataSet types

/**
 * A utility class for views in SLI dashboard. As a wrapper around assessment data passed onto
 *  dashboard views. Contains useful tools look up assessment data
 * 
 * @author syau
 *
 */
public class AssessmentResolver {
    List<Assessment> assessments;
    ViewConfig viewConfig;
    
    public static final String DATA_SET_TYPE = "assessment";

    /**
     * Constructor
     */
    public AssessmentResolver(List<Assessment> a, ViewConfig v) {
        assessments = a;
        viewConfig = v;
    }
    
    /**
     * Looks up a representation for the result of the assessment, taken by the student 
     * Returns the string representation of the result, identified by the datapoint ID
     */
    public String get(String dataPointId, Student student) {

        // This first implementation is gruelingly inefficient. But, whateves... it's gonna be 
        // thrown away. 

        // A) filter out students first
        List<Assessment> studentFiltered = new ArrayList();
        for (Assessment a : assessments) {
            if (a.getStudentId().equals(student.getUid())) {
                studentFiltered.add(a);
            }
        }
        if (studentFiltered.isEmpty()) { return ""; }

        // B) filter out assessments based on dataset path
        String assessmentName = extractAssessmentName(dataPointId);
        List<Assessment> studentAssessmentFiltered = new ArrayList();
        for (Assessment a : assessments) {
            if (a.getAssessmentName().equals(assessmentName)) {
                studentAssessmentFiltered.add(a);
            }
        }
        if (studentAssessmentFiltered.isEmpty()) { return ""; }

        // C) Apply time logic. For now, just get the latest... there should be some 
        //    classes that actually implement various timed logics. 
        String timeSlot = extractTimeSlot(dataPointId);
        Collections.sort(studentAssessmentFiltered, new Comparator<Assessment>() {
            public int compare(Assessment o1, Assessment o2) {
                return o1.getYear() - o2.getYear();
            }
        });

        // D) get the data point
        Assessment chosenAssessment = studentFiltered.get(0);
        String dataPointName = extractDataPointName(dataPointId);
        if (dataPointName == null) { return ""; }
        if (dataPointName.equals("level")) { return chosenAssessment.getPerfLevelAsString(); }
        if (dataPointName.equals("scaleScore")) { return chosenAssessment.getScaleScoreAsString(); }
        if (dataPointName.equals("percentile")) { return chosenAssessment.getPercentileAsString(); }
        if (dataPointName.equals("lexileScore")) { return chosenAssessment.getLexileScoreAsString(); }

        return ""; 
    }

    // returns true iff this resolver's view config can resolve the data point 
    public boolean canResolve(String dataPointId) {
        return getDataPoint(dataPointId) != null;
    }

    // helper functions to extract names from the view config using the datapointid 
    private String extractAssessmentName(String dataPointId) {
        DataSet ds = getDataSet(dataPointId);
        return ds == null ? null : ds.getName();
    }
    private String extractTimeSlot(String dataPointId) {
        DataSet ds = getDataSet(dataPointId);
        return ds == null ? null : ds.getTimeSlot();
    }
    private String extractDataPointName(String dataPointId) {
        DataPoint dp = getDataPoint(dataPointId);
        return dp == null ? null : dp.getId(); // Assume data point's name is identical to id
    }
    private DataSet getDataSet(String dataPointId) {
        String [] dataPointPath = dataPointId.split("\\.");
        String dataSetName = dataPointPath[0];
        for (DataSet ds : viewConfig.getDataSet()) {
            if (ds.getType().equals(DATA_SET_TYPE) && ds.getId().equals(dataSetName)) {
                return ds;
            }
        }
        return null;
    }
    private DataPoint getDataPoint(String dataPointId) {
        String [] dataPointPath = dataPointId.split("\\.");
        String dataPointName = dataPointPath[1];
        DataSet ds = getDataSet(dataPointId);
        if (ds == null) { return null; }
        for (DataPoint dp : ds.getDataPoint()) {
            if (dp.getId().equals(dataPointName)) {
                return dp;
            }
        }
        return null;
    }
}

@@ -754,16 +754,316 @@
 sment%22;%0D
+%0A    public static final String DATA_POINT_NAME_PERFLEVEL = %22perfLevel%22;%0D%0A    public static final String DATA_POINT_NAME_SCALESCORE = %22scaleScore%22;%0D%0A    public static final String DATA_POINT_NAME_PERCENTILE = %22percentile%22;%0D%0A    public static final String DATA_POINT_NAME_LEXILESCORE = %22lexileScore%22;%0D
 %0A%0D%0A    /
@@ -2167,35 +2167,39 @@
 essment a : 
-assessments
+studentFiltered
 ) %7B%0D%0A       
@@ -2916,32 +2916,42 @@
 ssment = student
+Assessment
 Filtered.get(0);
@@ -3107,15 +3107,33 @@
 als(
-%22level%22
+DATA_POINT_NAME_PERFLEVEL
 )) %7B
@@ -3217,28 +3217,42 @@
 .equals(
-%22scaleScore%22
+DATA_POINT_NAME_SCALESCORE
 )) %7B ret
@@ -3333,28 +3333,42 @@
 .equals(
-%22percentile%22
+DATA_POINT_NAME_PERCENTILE
 )) %7B ret
@@ -3449,29 +3449,43 @@
 .equals(
-%22lexileScore%22
+DATA_POINT_NAME_LEXILESCORE
 )) %7B ret

Fix bug in view config-driven resolver code.