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

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

/**
 * 一定の時間間隔（timeStep）で、入力信号をサンプリングして出力するフィルタです。
 * 
 * setInitialTime()で開始時刻を指定しなかった場合は、最初のSignalMessageの時刻を、
 * timeStepの倍数になるように切り上げた時刻から、サンプリングを開始します。
 * （つまり、出力されるSignalMessageの時刻は、常にtimeStepの倍数になります）。
 * 
 * @author iwasaki
 */
public class PeriodicSignalSampler extends AbstractFilter {
	private boolean started_=false;
	private SignalInterpolator interpolator_;
	private long nextTime_=0;
	private long timeStep_=0;
	
	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;
				// +方向へ切り上げ
				long mod=nextTime_%timeStep_;
				if (mod>0) nextTime_+=timeStep_-mod;
				else if (mod<0) nextTime_-=mod;
			}
			if (nextTime_<=time) {
				if (interpolator_.addSample(sig)) {
					for(;nextTime_<=time;nextTime_+=timeStep_) {
						outputMessage(interpolator_.getAtTime(nextTime_));
					}
				}else{
					// ignore
				}
			}
		}else{
			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;
	}

}
