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

package jp.sourceforge.orangesignal.ta.candle.generator;

import static jp.sourceforge.orangesignal.ta.candle.generator.CandlestickGeneratorSettingType.DOJI;
import static jp.sourceforge.orangesignal.ta.candle.generator.CandlestickGeneratorSettingType.FAR;
import static jp.sourceforge.orangesignal.ta.candle.generator.CandlestickGeneratorSettingType.LONG_BODY;
import static jp.sourceforge.orangesignal.ta.candle.generator.CandlestickGeneratorSettingType.LONG_SHADOW;
import static jp.sourceforge.orangesignal.ta.candle.generator.CandlestickGeneratorSettingType.NEAR;
import static jp.sourceforge.orangesignal.ta.candle.generator.CandlestickGeneratorSettingType.NO_SHADOW;
import static jp.sourceforge.orangesignal.ta.candle.generator.CandlestickGeneratorSettingType.SAME;

import java.util.EnumMap;
import java.util.Map;

import jp.sourceforge.orangesignal.ta.candle.generator.CandlestickGeneratorSetting.Range;


/**
 * 既定のローソク足生成設定群情報を提供します。
 * 
 * @author 杉澤 浩二
 */
public class DefaultCandlestickGeneratorSettings implements CandlestickGeneratorSettings {

	/**
	 * デフォルトコンストラクタです。
	 */
	public DefaultCandlestickGeneratorSettings() {
		setSettings(createDefaultSettings());
		setLengthPeriod(10);
		setDistancePeriod(5);
	}

	/**
	 * コンストラクタです。
	 * 
	 * @param settings ローソク足生成設定情報のリスト
	 * @param lengthPeriod ローソク足の長さ基準期間
	 * @param distancePeriod ローソク足の距離基準期間
	 * @throws NullPointerException ローソク足生成設定情報のリストに <code>null</code> が指定された場合
	 * @throws IllegalArgumentException 基準期間に <code>0</code> 以下の値が指定された場合
	 */
	public DefaultCandlestickGeneratorSettings(
			final Map<CandlestickGeneratorSettingType, CandlestickGeneratorSetting> settings,
			final int lengthPeriod, final int distancePeriod)
	throws NullPointerException, IllegalArgumentException {
		setSettings(settings);
		setLengthPeriod(lengthPeriod);
		setDistancePeriod(distancePeriod);
	}

	/**
	 * ローソク足生成設定情報のリストです。<p>
	 * 
	 * <dl>
	 * <dt>{@link CandlestickGeneratorSettingType#VERY_LONG_BODY}</dt>
	 * <dd>
	 * 非常に大きい実体用のローソク足生成設定情報です。
	 * 実体の長さ平均の 3 倍を基準値とします。
	 * 実体の長さが基準値より大きい場合、実体は非常に大きいとします。
	 * </dd>
	 * </dl>
	 */
	private Map<CandlestickGeneratorSettingType, CandlestickGeneratorSetting> settings;

	/**
	 * ローソク足生成設定情報のリストを返します。
	 * 
	 * @return ローソク足生成設定情報のリスト
	 */
	public final Map<CandlestickGeneratorSettingType, CandlestickGeneratorSetting> getSettings() {
		return settings;
	}

	/**
	 * ローソク足生成設定情報のリストを設定します。
	 * 
	 * @param settings ローソク足生成設定情報のリスト
	 * @throws NullPointerException ローソク足生成設定情報のリストに <code>null</code> が指定された場合
	 */
	public final void setSettings(final Map<CandlestickGeneratorSettingType, CandlestickGeneratorSetting> settings) throws NullPointerException {
		if (settings == null)
			throw new NullPointerException();
		// FIXME - ここにリストの内容を検査するコードを記述します。
		this.settings = settings;
	}

	@Override
	public final CandlestickGeneratorSetting getSetting(final CandlestickGeneratorSettingType type) {
		return settings.get(type);
	}

	/**
	 * ローソク足の長さ基準期間を保持します。
	 */
	private int lengthPeriod;

	@Override public final int getLengthPeriod() { return lengthPeriod; }

	/**
	 * ローソク足の長さ基準期間を設定します。
	 * 
	 * @param lengthPeriod ローソク足の長さ基準期間
	 * @throws IllegalArgumentException ローソク足の長さ基準期間に <code>0</code> 以下の値が指定された場合
	 */
	public final void setLengthPeriod(final int lengthPeriod) throws IllegalArgumentException {
		if (lengthPeriod <= 0)
			throw new IllegalArgumentException();
		this.lengthPeriod = lengthPeriod;
	}

	/**
	 * ローソク足の距離基準期間を保持します。
	 */
	private int distancePeriod;

	@Override public final int getDistancePeriod() { return distancePeriod; }

	/**
	 * ローソク足の距離基準期間を設定します。
	 * 
	 * @param distancePeriod ローソク足の距離基準期間
	 * @throws IllegalArgumentException ローソク足の距離基準期間に <code>0</code> 以下の値が指定された場合
	 */
	public final void setDistancePeriod(final int distancePeriod) throws IllegalArgumentException {
		if (distancePeriod <= 0)
			throw new IllegalArgumentException();
		this.distancePeriod = distancePeriod;
	}

	/**
	 * 既定のローソク足生成設定情報のリストを構築して返します。<p>
	 * この実装では以下のリストを構築します。
	 * 
	 * <dl>
	 * <dt>{@link CandlestickGeneratorSettingType#LONG_BODY}</dt>
	 * <dd>
	 * 長い胴体のローソク足生成設定情報です。<br>
	 * 胴体の長さ平均を基準値とします。<br>
	 * 胴体の長さが基準値より長い場合、胴体は長いとします。
	 * </dd>
	 * <dt>{@link CandlestickGeneratorSettingType#DOJI}</dt>
	 * <dd>
	 * 同時のローソク足生成設定情報です。<br>
	 * ローソクの長さ平均の 10% を基準値とします。<br>
	 * 胴体の長さが基準値より短い場合、胴体は同時とします。
	 * </dd>
	 * <dt>{@link CandlestickGeneratorSettingType#LONG_SHADOW}</dt>
	 * <dd>
	 * 影(ヒゲ)が長いローソク足生成設定情報です。<br>
	 * 実体長さ平均を基準値とします。<br>
	 * 上影または下影の長さが基準値より大きい場合、上影または下影は長いとします。
	 * </dd>
	 * <dt>{@link CandlestickGeneratorSettingType#NO_SHADOW}</dt>
	 * <dd>
	 * 影(ヒゲ)が無い(極短含む)用のローソク足生成設定情報です。<br>
	 * ローソクの長さ平均の 10% を基準値とします。<br>
	 * 上影または下影の長さが基準値より小さい場合、上影または下影は短いとします。
	 * </dd>
	 * <dt>{@link CandlestickGeneratorSettingType#SAME}</dt>
	 * <dd>
	 * 同距離用のローソク足生成設定情報です。<br>
	 * ローソクの長さ平均の 5% を基準値とします。<br>
	 * 対象との誤差が基準値未満の場合、同距離とします。
	 * </dd>
	 * <dt>{@link CandlestickGeneratorSettingType#NEAR}</dt>
	 * <dd>
	 * 近距離用のローソク足生成設定情報です。<br>
	 * ローソクの長さ平均の 20% を基準値とします。<br>
	 * 対象との誤差が基準値未満の場合、近距離とします。
	 * </dd>
	 * <dt>{@link CandlestickGeneratorSettingType#FAR}</dt>
	 * <dd>
	 * 遠距離用のローソク足生成設定情報です。<br>
	 * ローソクの長さ平均の 60% を基準値とします。<br>
	 * 対象との誤差が基準値より大きい場合、遠距離とします。
	 * </dd>
	 * </dl>
	 * 
	 * @return ローソク足生成設定情報のリスト
	 */
	protected static final Map<CandlestickGeneratorSettingType, CandlestickGeneratorSetting> createDefaultSettings() {
		final Map<CandlestickGeneratorSettingType, CandlestickGeneratorSetting> settings =
			new EnumMap<CandlestickGeneratorSettingType, CandlestickGeneratorSetting>(CandlestickGeneratorSettingType.class);

		settings.put(LONG_BODY, new CandlestickGeneratorSetting(Range.BODY, 1.0));
		settings.put(DOJI, new CandlestickGeneratorSetting(Range.BODY, 0.1));
		settings.put(LONG_SHADOW, new CandlestickGeneratorSetting(Range.BODY, 1.0));
		settings.put(NO_SHADOW, new CandlestickGeneratorSetting(Range.CANDLE, 0.1));
		settings.put(SAME, new CandlestickGeneratorSetting(Range.CANDLE, 0.05));
		settings.put(NEAR, new CandlestickGeneratorSetting(Range.CANDLE, 0.2));
		settings.put(FAR, new CandlestickGeneratorSetting(Range.CANDLE, 0.6));

		return settings;
	}

}
