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

import jp.hasc.hasctool.core.data.ScalarSignalMessage;
import jp.hasc.hasctool.core.data.VectorSignalMessages;
import jp.hasc.hasctool.core.runtime.RuntimeContext;
import jp.hasc.hasctool.core.runtime.filter.AbstractFilter;
import jp.hasc.hasctool.core.runtime.filter.window.WindowFunction;
import jp.hasc.hasctool.core.data.Complex;

/**
 * 低周波領域を通過させるフィルタです
 * @author hiro, iwasaki
 */

public class LowPassFilter extends AbstractFilter {

	private int length_;//配列の大きさ
	private Complex[] input_;//入力
	private int next_;//現在の位置
	private boolean fill_;
	private int cutoffFrequency_;//カットオフ周波数
	private FFT fft_;//FFT
	private WindowFunction wf_;//窓関数

	@Override
	public void setup(RuntimeContext context) {
		super.setup(context);
		if(cutoffFrequency_>length_){
			cutoffFrequency_ = length_;
		}
		input_ = new Complex[length_];
		next_ = 0;
	}

	public void setSampleNum(int samplenum) {
		length_=samplenum;
	}

	public void setCutoffFrequency(int cf) {
		cutoffFrequency_=cf;
	}

	protected void setdata(Complex data){
		input_[next_] = data;
		next_ = (next_+1)%length_;
	}


	@Override
	public void processMessage(Object message) throws InterruptedException {
		if (message instanceof ScalarSignalMessage) {
			// ScalarSignalMessageの場合
			ScalarSignalMessage ssig=(ScalarSignalMessage)message;
			this.setdata(new Complex(ssig.getScalarValue(), 0));
			if(next_ == 0 && !(fill_)){
				fill_ = true;
			}
			if(fill_){
				Complex[] data = new Complex[length_];
				for(int i=0; i<length_; i++){
					int j = (i+next_)%length_;
					data[i] = input_[j];
				}
				wf_ = new WindowFunction();
				data = wf_.WindowHanning(data);
				//フーリエ変換
				fft_ = new FFT(false);
				fft_.setdata(data);
				fft_.execute();
				Complex[] data2 = fft_.getdata();
				//LowPassFilter
				int cf = cutoffFrequency_;
				for(int i=0; i<length_; i++){
					int j = i+1;
					if(j > cf && j < (length_+1 - cf) ){
						data2[i] = new Complex(0, 0);
					}
				}
				//逆フーリエ変換
				fft_ = new FFT(true);
				fft_.setdata(data2);
				fft_.execute();
				Complex[] data3 = fft_.getdata();
				double newValue[] = new double[1];
				newValue[0] = data3[length_/2].re();
				// 結果を出力
				outputMessage(VectorSignalMessages.create(ssig.getTime(), newValue));
			}
		}else{
			// その他のメッセージ（BEGIN, ENDなど）はそのまま出力
			outputMessage(message);
		}
	}
}
