package jp.hasc.hasctool.core.runtime.filter.evaluation;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import jp.hasc.hasctool.core.data.EnumCommand;
import jp.hasc.hasctool.core.runtime.RuntimeContext;
import jp.hasc.hasctool.core.runtime.filter.AbstractFilter;
import jp.hasc.hasctool.core.util.CSVUtil;
import jp.hasc.hasctool.core.util.CoreUtil;


/**
 *　評価を行うフィルタ
 *　（イベントラベルに対応しました）
 * @author hiro
 */
public class EvaluationFilter extends AbstractFilter{

	String element_;
	EvaluationData evalData_;
	String labelFilePath_;
	ArrayList<MyData> correctDList_ ;
	ArrayList<MyData> preDList_;
	double[] sumT;

	public void setLabelFilePath(String path) {
		labelFilePath_ = path;
	}

	public void setLabelPathFromCSVFilePath(String path) {
		labelFilePath_ = path.replaceAll("\\.csv$", ".label");
	}

	public void setElement(String element) {
		element_ = element;
	}

	class MyData{

		double startTime_;
		double endTime_;
		String label_;

		public MyData(){
		}
		public void setTime(double t1, double t2){
			startTime_ = t1;
			endTime_ = t2;
		}
		public void setLabel(String label){
			label_ = label;
		}
		public double getStartTime(String label){
			if(0 <= label_.indexOf(label)){
				return startTime_;
			} else {
				return -1.0;
			}
		}
		public double getEndTime(String label){
			if(0 <= label_.indexOf(label)){
				return endTime_;
			} else {
				return -1.0;
			}
		}
	}

	@Override
	public void setup(RuntimeContext context) {
		super.setup(context);
		this.start();
	}

	private void start(){
		String[] elementList = element_.split(",");
		sumT = new double[elementList.length];
		correctDList_ = new ArrayList<MyData>();
		preDList_ = new ArrayList<MyData>();
	}

	private void setData(String[] input, ArrayList<MyData> mdList) {
		int len = input.length;
		if(len == 3 && !(input[1].equals(""))){
			MyData md = new MyData();
			md.setTime(Double.parseDouble(input[0]), Double.parseDouble(input[1]));
			md.setLabel(input[2]);
			mdList.add(md);
		}
	}

	private void evaluate(){
		int len = evalData_.getElementNum();
		for(int i=0; i<len; i++){
			String metaLabel = evalData_.getElement(i);
			double[] partT = new double[element_.split(",").length];
			for(int j=0; j<len; j++){
				String evalLabel = evalData_.getElement(j);
				partT[j] = getTimeLength(metaLabel, evalLabel);
				sumT[i] += partT[j];
			}
			for(int k=0; k<len; k++){
				double percent = 0.0;
				if(sumT[i] != 0)percent = (partT[k] / sumT[i])*100.0;
				evalData_.setData(percent, i, k);
			}
		}
	}

	private double getTimeLength(String metaLab, String evalLab){
		int len1 = correctDList_.size();
		int len2 = preDList_.size();
		double tlength = 0.0;
		for(int m=0; m<len1; m++){
			double ms = correctDList_.get(m).getStartTime(metaLab);
			double me = correctDList_.get(m).getEndTime(metaLab);
			if(ms != -1.0 && me != -1.0){
				for(int n=0; n<len2; n++){
					double ns = preDList_.get(n).getStartTime(evalLab);
					double ne = preDList_.get(n).getEndTime(evalLab);
					if(ns != -1.0 && ne != -1.0){
						if(ns <= ms){
							if(ne >= ms){
								if(ne <= me){
									tlength += ne - ms;
								}else{
									tlength += me - ms;
								}
							}
						} else {
							if(ns <= me){
								if(ne >= me){
									tlength += me - ns;
								}else{
									tlength += ne - ns;
								}
							}
						}
					}
				}
			}
		}
		return tlength;
	}

	@Override
	public void processMessage(Object message) throws InterruptedException {
		if (message instanceof String) {
			// label line
			String line=(String)message;
			String[] columns = CSVUtil.parseCSVRecord(line);
			setData(columns, preDList_);

		}else if (message==EnumCommand.BEGIN) {
			try{
				InputStream inps;
				try {
					inps = getRuntimeContext().getFileStreamProvider().openInputStream(labelFilePath_);
					BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inps, RuntimeContext.DEFAULT_CHARSET));
					while(true){
						String line = bufferedReader.readLine();
						if (line == null) break;
						String[] columns = CSVUtil.parseCSVRecord(line);
						setData(columns, correctDList_);
					}
					bufferedReader.close();
					inps.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}catch(RuntimeException ex) {
				CoreUtil.throwAsRuntimeException(ex);
			}

		} else if (message == EnumCommand.END) {
			evalData_ = new EvaluationData(element_);
			evaluate();
			String[][] evalTable = evalData_.getData();
			int len = evalTable[0].length;
			outputMessage(EnumCommand.BEGIN);
			for(int i=0; i<len-1; i++){
				String metaLabel = evalData_.getElement(i);
				outputMessage(metaLabel + "," + sumT[i]);
			}
			for(int i=0; i<len; i++){
				String row = evalTable[i][0];
				for(int j=1; j<len; j++){
					row = row + "," + evalTable[i][j];
				}
				outputMessage(row);
			}
			outputMessage("Overall," + evalData_.getOverAll());
			outputMessage(EnumCommand.END);
		} else {
		}
	}
}
