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

import jp.hasc.hasctool.core.data.EnumCommand;
import jp.hasc.hasctool.core.data.SignalMessage;
//import jp.hasc.hasctool.core.data.VectorSignalMessage;
import jp.hasc.hasctool.core.runtime.filter.AbstractFilter;

/**
 * 一定の時間間隔（timeStep）で、入力信号をサンプリングして出力するフィルタです。
 * 
 * setInitialTime()で開始時刻を指定しなかった場合は、最初のSignalMessageの時刻を、
 * timeStepの倍数になるように切り上げた時刻から、サンプリングを開始します。
 * （つまり、出力されるSignalMessageの時刻は、常にtimeStepの倍数になります）。
 *  また、出力を１つ分シフトし、１つ前のSignal までの時刻でしか出力しません。
 *
 *                   lastTime         time
 *                      |              |
 *                      v              v
 *  ----0*-----1------1-*----2------2--*-------------
 *      ^      ^      ^      ^      ^
 *      |      |      |      |      |
 *   nextTime
 * 
 *  上手の time のタイミングで、PeriodicSignalSampler は 2 まで出力
 *  しますが、ShiftedPeriodicSignalSampler は　1までしか出力しません。
 * 
 * @author iwasaki, kawaguti
 */
public class ShiftedPeriodicSignalSampler extends AbstractFilter {
	private boolean started_=false;
	private SignalInterpolator interpolator_;
	private long nextTime_=0;
	private long timeStep_=0;
	private long lastTime_ = 0; // for Shifted
	
	public void setInitialTime(long time) {
		if (started_) throw new IllegalStateException();
		nextTime_=time;
		started_=true;
	}

	@Override
	public void processMessage(Object message) throws InterruptedException {
		if (message instanceof SignalMessage) {
			SignalMessage sig = (SignalMessage) message;
			long time=sig.getTime();
			if (!started_) {
				started_=true;
				nextTime_=time;
				lastTime_ = nextTime_ - timeStep_;// omit first message
				// +方向へ切り上げ
//				long mod=nextTime_%timeStep_;
//				if (mod>0) nextTime_+=timeStep_-mod;
//				else if (mod<0) nextTime_-=mod;
//				System.out.println("Shifted:"+time+","+((VectorSignalMessage)sig).getVectorElement(0)+",Next:"+nextTime_+","+timeStep_+","+mod);
			}
			if (nextTime_<=time) {
				if (interpolator_.addSample(sig)) {
					for(;nextTime_<=lastTime_;nextTime_+=timeStep_) {
						outputMessage(interpolator_.getAtTime(nextTime_));
					}
				}else{
					// ignore
				}
			}
			lastTime_ = time;
		}else{
			if(message==EnumCommand.END){// 最後の部分を出力
				for(;nextTime_<=lastTime_;nextTime_+=timeStep_) {
					outputMessage(interpolator_.getAtTime(nextTime_));
				}
			}
			outputMessage(message);
		}
		
	}

	public SignalInterpolator getInterpolator() {
		return interpolator_;
	}

	public void setInterpolator(SignalInterpolator interpolator) {
		interpolator_ = interpolator;
	}

	public long getTimeStep() {
		return timeStep_;
	}

	public void setTimeStep(long timeStep) {
		if (timeStep<=0) throw new IllegalArgumentException();
		timeStep_ = timeStep;
	}

}
