/*
 * Copyright (c) 2006-2009 OrangeSignal.com All rights reserved.
 * 
 * これは Apache ライセンス Version 2.0 (以下、このライセンスと記述) に
 * 従っています。このライセンスに準拠する場合以外、このファイルを使用
 * してはなりません。このライセンスのコピーは以下から入手できます。
 * 
 * http://www.apache.org/licenses/LICENSE-2.0.txt
 * 
 * 適用可能な法律がある、あるいは文書によって明記されている場合を除き、
 * このライセンスの下で配布されているソフトウェアは、明示的であるか暗黙の
 * うちであるかを問わず、「保証やあらゆる種類の条件を含んでおらず」、
 * 「あるがまま」の状態で提供されるものとします。
 * このライセンスが適用される特定の許諾と制限については、このライセンス
 * を参照してください。
 */

package jp.sf.orangesignal.trading.commission;

import jp.sf.orangesignal.ta.PercentageScale;

/**
 * 手数料率情報を提供します。
 * 
 * @author 杉澤 浩二
 */
public class RateCommission extends CommissionUnit {

	private static final long serialVersionUID = -904663648825498390L;

	/**
	 * 手数料率を <code>0</code> としてこのクラスを構築するデフォルトコンストラクタです。
	 */
	public RateCommission() {
		this(0, PercentageScale.PERCENT, 0, 0, 0);
	}

	/**
	 * 手数料率を指定してこのクラスを構築するコンストラクタです。
	 * 
	 * @param rate 手数料率
	 * @param scale 手数料率の単位
	 */
	public RateCommission(final double rate, final PercentageScale scale) {
		this(rate, scale, 0, 0, 0);
	}

	/**
	 * 手数料率と追加手数料を指定してこのクラスを構築するコンストラクタです。
	 * 
	 * @param rate 手数料率
	 * @param scale 手数料率の単位
	 * @param adding 追加手数料
	 */
	public RateCommission(final double rate, final PercentageScale scale, final double adding) {
		this(rate, scale, adding, 0, 0);
	}

	/**
	 * 手数料率と手数料の上限および下限を指定してこのクラスを構築するコンストラクタです。
	 * 
	 * @param rate 手数料率
	 * @param scale 手数料率の単位
	 * @param min 下限手数料
	 * @param max 上限手数料
	 */
	public RateCommission(final double rate, final PercentageScale scale, final double min, final double max) {
		this(rate, scale, 0, min, max);
	}

	/**
	 * 手数料率と追加手数料、手数料の上限および下限を指定してこのクラスを構築するコンストラクタです。
	 * 
	 * @param rate 手数料率
	 * @param scale 手数料率の単位
	 * @param adding 追加手数料
	 * @param min 下限手数料
	 * @param max 上限手数料
	 */
	public RateCommission(final double rate, final PercentageScale scale, final double adding, final double min, final double max) {
		this.rate = rate;
		this.scale = scale;
		this.adding = adding;
		this.min = min;
		this.max = max;
	}

	/**
	 * 手数料率を指定してこのクラスを構築するコンストラクタです。
	 * 
	 * @param base 基準価格
	 * @param rate 手数料率
	 * @param scale 手数料率の単位
	 */
	public RateCommission(final double base, final double rate, final PercentageScale scale) {
		this(base, rate, scale, 0, 0, 0);
	}

	/**
	 * 手数料率と追加手数料を指定してこのクラスを構築するコンストラクタです。
	 * 
	 * @param base 基準価格
	 * @param rate 手数料率
	 * @param scale 手数料率の単位
	 * @param adding 追加手数料
	 */
	public RateCommission(final double base, final double rate, final PercentageScale scale, final double adding) {
		this(base, rate, scale, adding, 0, 0);
	}

	/**
	 * 手数料率と手数料の上限および下限を指定してこのクラスを構築するコンストラクタです。
	 * 
	 * @param base 基準価格
	 * @param rate 手数料率
	 * @param scale 手数料率の単位
	 * @param min 下限手数料
	 * @param max 上限手数料
	 */
	public RateCommission(final double base, final double rate, final PercentageScale scale, final double min, final double max) {
		this(base, rate, scale, 0, min, max);
	}

	/**
	 * 手数料率と追加手数料、手数料の上限および下限を指定してこのクラスを構築するコンストラクタです。
	 * 
	 * @param base 基準価格
	 * @param rate 手数料率
	 * @param scale 手数料率の単位
	 * @param adding 追加手数料
	 * @param min 下限手数料
	 * @param max 上限手数料
	 */
	public RateCommission(final double base, final double rate, final PercentageScale scale, final double adding, final double min, final double max) {
		super(base);
		this.rate = rate;
		this.scale = scale;
		this.adding = adding;
		this.min = min;
		this.max = max;
	}

	/**
	 * 手数料率を保持します。
	 */
	private double rate;

	/**
	 * 手数料率を返します。
	 * 
	 * @return 手数料率
	 */
	public double getRate() { return rate; }

	/**
	 * 手数料率を設定します。
	 * 
	 * @param rate 手数料率
	 */
	public void setRate(final double rate) { this.rate = rate; }

	/**
	 * 手数料率の単位を保持します。
	 */
	private PercentageScale scale;

	/**
	 * 手数料率の単位を返します。
	 * 
	 * @return 手数料率の単位
	 */
	public PercentageScale getScale() { return scale; }

	/**
	 * 手数料率の単位を設定します。
	 * 
	 * @param scale 手数料率の単位
	 */
	public void setScale(final PercentageScale scale) { this.scale = scale; }

	/**
	 * 追加手数料を保持します。
	 */
	private double adding;

	/**
	 * 追加手数料を返します。
	 * 
	 * @return 追加手数料
	 */
	public double getAdding() { return adding; }

	/**
	 * 追加手数料を設定します。
	 * 
	 * @param adding 追加手数料
	 */
	public void setAdding(final double adding) { this.adding = adding; }

	/**
	 * 下限手数料を保持します。
	 */
	private double min;

	/**
	 * 下限手数料を返します。
	 * 
	 * @return 下限手数料
	 */
	public double getMin() { return min; }

	/**
	 * 下限手数料を返します。
	 * 
	 * @param min 下限手数料
	 */
	public void setMin(final double min) { this.min = min; }

	/**
	 * 上限手数料を保持します。
	 */
	private double max;

	/**
	 * 上限手数料を返します。
	 * 
	 * @return 上限手数料
	 */
	public double getMax() { return max; }

	/**
	 * 上限手数料を設定します。
	 * 
	 * @param max 上限手数料
	 */
	public void setMax(final double max) { this.max = max; }

	/**
	 * <p>指定された価格と数量から手数料を計算して返します。</p>
	 * <pre>
	 * 手数料＝価格×数量÷手数料率の単位×手数料率＋追加手数料
	 * ※但し、上限手数料が指定されている場合、手数料の上限値を上限手数料とする。
	 * ※但し、下限手数料が指定されている場合、手数料の下限値を下限手数料とする。
	 * </pre>
	 * 
	 * @param price 価格
	 * @param quantity 数量
	 * @return 手数料
	 */
	@Override
	public double calcCommission(final double price, final int quantity) {
		double result = price * quantity / scale.scale() * rate + adding;
		if (min != 0 && result < min)
			result = min;
		if (max != 0 && result > max)
			result = max;
		return result;// + getSlippage();
	}

}
