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

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import jp.hasc.hasctool.core.data.EnumCommand;
import jp.hasc.hasctool.core.runtime.filter.AbstractFilter;
import jp.hasc.hasctool.core.runtime.RuntimeContext;
import jp.hasc.hasctool.core.util.CoreUtil;

/**
 * Event情報に基づいて Event間毎にラベルファイルを区切る
 * @author hiro
 */

public class EventLabelCutter extends AbstractFilter{

	private String srcString_;
	private String srcRegex_;
	private String destString_;

	boolean start_ = true;
	String filePath_;
	String outPath_;
	LabelData[] ld_ = new LabelData[200];// currently only allow 200 labels.
	int index_ = 0;
	double eventSt_ = -1.0;
	double eventEn_;

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

	int fileCount_=0;
	OutputStream openOutStream(String label){
		String outPath = filePath_; // like "$(projectRoot)/activity/subj01/day01/set01-acc.csv"
		if (srcString_!=null) {
			outPath = filePath_.replace(srcString_, destString_);
		}else if (srcRegex_!=null) {
			outPath = filePath_.replaceAll(srcRegex_, destString_);
		}
		int li = outPath.lastIndexOf(".csv"); // find last ".csv"
		outPath = outPath.substring(0,li);// remove .csv
		outPath += "/"+label+"/seg"+Integer.toString(1000+fileCount_)+".label";
		outPath_ = outPath.substring(0,li) 
		+ "/"+label+"/seg"+Integer.toString(1000+fileCount_)+".csv";
		fileCount_++;

		OutputStream oups = getRuntimeContext().getFileStreamProvider().openOutputStream(outPath);
		return oups;
	}

	@Override
	public void processMessage(Object message) throws InterruptedException {
		if (message instanceof String) {
			String line =(String)message;
			if(start_){// first line should contain FilePath of the data.
				String[] row = line.split(":");
				filePath_ = row[1];
				start_ = false;
			}else if(line.contains(",")){ // assume labels do not overlap and sorted.
				String[] row = line.split(",");
				if(eventSt_ == -1.0){
					eventSt_ = Double.parseDouble(row[0]);
				}else if(row[1].equals("")){
					eventEn_ = Double.parseDouble(row[0]);
					ld_[index_] = new LabelData(eventSt_, eventEn_, row[2]);
					index_++;
					eventSt_ = eventEn_;
				}
			}
		} else if (message == EnumCommand.END) {
			try{
				// open signal file
				String[] path = filePath_.split("\\.");
				InputStream inps = getRuntimeContext().getFileStreamProvider().openInputStream(path[0]+".label");
				BufferedReader bufferedReader = 
					new BufferedReader(new InputStreamReader(inps, RuntimeContext.DEFAULT_CHARSET));

				int ind=0; // for SignalName;
				boolean finished = true;
				OutputStream ost=null;
				BufferedWriter bw=null;
				String labelLine = "";
				boolean target = false;
				
				while(true){
					if( finished && ind < index_){
						ost = openOutStream(ld_[ind].label_);
						bw = new BufferedWriter(new OutputStreamWriter(ost,RuntimeContext.DEFAULT_CHARSET));
						finished = false; 
					}
					String line = bufferedReader.readLine();
					if (line == null) {
						break;
					} else{ // read signal line.
						String[] val = line.split(",");
						if(val.length != 3){
							if(val[0].indexOf("#targetfile:", 0)!=-1){
								bw.write("#targetfile:"+outPath_);
								bw.newLine();
							}
							continue;
						}
						double time = Double.parseDouble(val[0]);
						if(target){
							bw.write("#targetfile:"+outPath_);
							bw.newLine();
							if(!(labelLine.equals("")) && time<Double.parseDouble(labelLine.split(",")[1])){
								bw.write(labelLine);
								bw.newLine();
								labelLine = "";
							}
							target=false;
						}
						
						if( ld_[ind].start_ > time) continue;
												
						if( ld_[ind].end_ <= time ) { // finished 
							if(!finished){ // file opened
								bw.close();
								target = true;
								ost.close();
								finished = true;
								if(ind < index_){
									ind++;
								}else{
									break; // finished all labals
								}
							}
						}else{ // start < time < end
							bw.write(line);
							bw.newLine();
							labelLine = line;
						}	
					}

				}// while(true)
				if(!finished){ // file opened
					bw.close();
					ost.close();
				}							
				bufferedReader.close();
				inps.close();
			} catch (IOException ex) {
				CoreUtil.throwAsRuntimeException(ex);
			} catch (RuntimeException ex) {
			}
			outputMessage(EnumCommand.END);
		} else {
			//BEGIN message
			outputMessage(message);
		}
	}

	/**
	 * 置換元の文字列を指定します。
	 */
	public void setSrcString(String srcString) {
		srcString_ = srcString;
	}

	/**
	 * 置換先の文字列を指定します。
	 */
	public void setDestString(String destString) {
		destString_ = destString;
	}

	/**
	 * 置換元の文字列を正規表現で指定します。（srcStringがnullの場合のみ有効）
	 */
	public void setSrcRegex(String srcStringAsRegexp) {
		srcRegex_ = srcStringAsRegexp;
	}

}
