package jp.hasc.hasctool.core.runtime.filter.file.label;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
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 LabelMerger extends AbstractFilter{

	String labelFilePath_;
	ArrayList<MyData> fDList_ ;
	ArrayList<MyData> sDList_;
	ArrayList<MyData> nDList_ ;
	double timeStep_ = 0.01;//単位：sec

	public void setTimeStep(double tstep) {
		timeStep_ = tstep;
	}

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

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

	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 String getLabel(){
			return label_;
		}
		public double getStartTime(){
			return startTime_;
		}
		public double getEndTime(){
			return endTime_;
		}
		public String getLabelInf(){
			return startTime_+","+endTime_+","+label_;
		}
	}

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

	private void start(){
		fDList_ = new ArrayList<MyData>();
		sDList_ = new ArrayList<MyData>();
		nDList_ = new ArrayList<MyData>();
	}

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

	private void modify(){
		int len1 = fDList_.size();
		int len2 = sDList_.size();
		double start = Double.MAX_VALUE;
		double end =  Double.MIN_VALUE;
		for(int f=0; f<len1; f++){
			double fs = fDList_.get(f).getStartTime();
			double fe = fDList_.get(f).getEndTime();
			if(start > fs)start = fs;
			if(end < fe)end = fe;
		}
		for(int s=0; s<len2; s++){
			double ss = sDList_.get(s).getStartTime();
			double se = sDList_.get(s).getEndTime();
			if(start > ss)start = ss;
			if(end < se)end = se;
		}
		double time = start;
		while(time < end){
			String label = getLabel(time);
			if(!(label.equals(""))){
				MyData md = new MyData();
				BigDecimal bi1 = new BigDecimal(String.valueOf(time));
				double st = bi1.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
				BigDecimal bi2 = new BigDecimal(String.valueOf(time+timeStep_));
				double et = bi2.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
				md.setTime(st, et);
				md.setLabel(label);
				nDList_.add(md);
			}
			time += timeStep_;
		}
	}

	private String getLabel(double time){
		int len1 = fDList_.size();
		int len2 = sDList_.size();
		String label1 = "";
		String label2 = "";
		for(int f=0; f<len1; f++){
			if(time > fDList_.get(f).getStartTime()){
				if(time < fDList_.get(f).getEndTime()){
					label1 = fDList_.get(f).getLabel();
					break;
				}
			}
		}
		for(int s=0; s<len2; s++){
			if(time >= sDList_.get(s).getStartTime()){
				if(time <= sDList_.get(s).getEndTime()){
					label2 = sDList_.get(s).getLabel();
					break;
				}
			}
		}
		if(label1.equals(label2) && !(label1.equals(""))){
			return label1;
		} else {
			return "nan";
		}
	}

	@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, sDList_);

		}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, fDList_);
					}
					bufferedReader.close();
					inps.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}catch(RuntimeException ex) {
				CoreUtil.throwAsRuntimeException(ex);
			}

		} else if (message == EnumCommand.END) {
			modify();
			int len = nDList_.size();
			outputMessage(EnumCommand.BEGIN);
			outputMessage("#targetfile:"+labelFilePath_);
			for(int i=0; i<len; i++){
				outputMessage(nDList_.get(i).getLabelInf());
			}
			outputMessage(EnumCommand.END);
		} else {
		}
	}
}
