/*
 * Copyright (c) 2006-2009 OrangeSignal.com All rights reserved.
 */

package jp.sourceforge.orangesignal.ta.dataset;

import static jp.sourceforge.orangesignal.ta.ArrayDataConverter.toTechnicalPrice;
import static jp.sourceforge.orangesignal.ta.ArrayDataConverter.toTechnicalVolume;
import jp.sourceforge.orangesignal.ta.candle.Candlestick;
import jp.sourceforge.orangesignal.ta.candle.generator.CandlestickGenerator;
import jp.sourceforge.orangesignal.ta.result.FourPrice;

/**
 * <p>テクニカル指標計算用の価格データを保持する標準的な時系列データセットを提供します。</p>
 * 
 * @author 杉澤 浩二
 * @since 1.1
 */
public class StandardDataset extends TimeSeriesDataset {

	/**
	 * ローソク足データを保持します。
	 */
	private Candlestick[] candlestick;

	/**
	 * <p>他のデータセットからこのクラスを構築するコンストラクタです。</p>
	 * 
	 * @param dataset データセット
	 */
	public StandardDataset(final TimeSeriesDataset dataset) {
		this(dataset, true);
	}

	/**
	 * <p>他のデータセットからこのクラスを構築するコンストラクタです。</p>
	 * 
	 * @param dataset データセット
	 * @param candlestick ローソク足データを生成するかどうか
	 */
	public StandardDataset(final TimeSeriesDataset dataset, final boolean candlestick) {
		super(dataset);
		setupTechnicalPrice();
		if (candlestick)
			this.candlestick = new CandlestickGenerator().generate(getDate(), getOpen(), getHigh(), getLow(), getClose());
	}

	/**
	 * 4本値及び出来高からテクニカル指標計算用データをこのクラスのデータセットへ設定します。
	 */
	private final void setupTechnicalPrice() {
		Number[] array;

		array = getOpen();
		if (array != null) {
			array = toTechnicalPrice(array);
			setData(DefaultDataType.TECHNICAL_OPEN, array);
		}

		array = getHigh();
		if (array != null) {
			array = toTechnicalPrice(array);
			setData(DefaultDataType.TECHNICAL_HIGH, array);
		}

		array = getLow();
		if (array != null) {
			array = toTechnicalPrice(array);
			setData(DefaultDataType.TECHNICAL_LOW, array);
		}

		array = getClose();
		if (array != null) {
			array = toTechnicalPrice(array);
			setData(DefaultDataType.TECHNICAL_CLOSE, array);
		}

		array = getVolume();
		if (array != null) {
			array = toTechnicalVolume(array);
			setData(DefaultDataType.TECHNICAL_VOLUME, array);
		}
	}

	/**
	 * 指定された4本値の種類に対応するテクニカル指標計算用価格データを返します。
	 * 
	 * @param type 4本値の種類
	 * @return テクニカル指標計算用価格データ。又は <code>null</code>
	 */
	public final Number[] getTechnicalPrice(final FourPrice type) {
		switch (type) {
			case OPEN:
				return getTechnicalOpen();
			case HIGH:
				return getTechnicalHigh();
			case LOW:
				return getTechnicalLow();
			case CLOSE:
				return getTechnicalClose();
			default:
				return null;
		}
	}

	/**
	 * テクニカル指標計算用始値データを返します。
	 * 
	 * @return テクニカル指標計算用始値データ
	 */
	public final Number[] getTechnicalOpen() { return getData(DefaultDataType.TECHNICAL_OPEN); }

	/**
	 * テクニカル指標計算用高値データを返します。
	 * 
	 * @return テクニカル指標計算用高値データ
	 */
	public final Number[] getTechnicalHigh() { return getData(DefaultDataType.TECHNICAL_HIGH); }

	/**
	 * テクニカル指標計算用安値データを返します。
	 * 
	 * @return テクニカル指標計算用安値データ
	 */
	public final Number[] getTechnicalLow() { return getData(DefaultDataType.TECHNICAL_LOW); }

	/**
	 * テクニカル指標計算用終値データを返します。
	 * 
	 * @return テクニカル指標計算用終値データ
	 */
	public final Number[] getTechnicalClose() { return getData(DefaultDataType.TECHNICAL_CLOSE); }

	/**
	 * テクニカル指標計算用出来高データを返します。
	 * 
	 * @return テクニカル指標計算用出来高データ。テクニカル指標計算用出来高データが存在しない場合は <code>null</code>
	 */
	public final Number[] getTechnicalVolume() { return getData(DefaultDataType.TECHNICAL_VOLUME); }

	/**
	 * ローソク足データを返します。
	 * 
	 * @return ローソク足データ。ローソク足データが存在しない場合は <code>null</code>
	 */
	public Candlestick[] getCandlestick() { return candlestick; }

	/**
	 * ローソク足情報を返します。
	 * 
	 * @param i インデックス
	 * @return ローソク足情報。又は <code>null</code>
	 */
	public Candlestick getCandlestick(final int i) { return candlestick == null ? null : candlestick[i]; }

}
