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

package jp.sourceforge.orangesignal.trading.commission;

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

	private static final long serialVersionUID = 4645452184754354352L;

	/**
	 * 定額手数料を <code>0</code> としてこのクラスを構築するデフォルトコンストラクタです。
	 */
	public FixedCommission() {}

	/**
	 * 定額手数料を指定してこのクラスを構築するコンストラクタです。
	 * 
	 * @param commission 定額手数料
	 */
	public FixedCommission(final double commission) {
		this(0, commission, 0, 0, 0);
	}

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

	/**
	 * 定額手数料と段階的追加手数料を指定してこのクラスを構築するコンストラクタです。
	 * 
	 * @param base 基準価格
	 * @param commission 定額手数料
	 * @param step 一段階あたりの値幅
	 * @param adding 一段階あたりの追加手数料
	 */
	public FixedCommission(final double base, final double commission, final double step, final double adding) {
		this(base, commission, step, adding, 0);
	}

	/**
	 * 定額手数料と段階的追加手数料および上限手数料を指定してこのクラスを構築するコンストラクタです。
	 * 
	 * @param base 基準価格
	 * @param commission 定額手数料
	 * @param step 一段階あたりの値幅
	 * @param adding 一段階あたりの追加手数料
	 * @param max 上限手数料
	 */
	public FixedCommission(final double base, final double commission, final double step, final double adding, final double max) {
		super(base);
		this.commission = commission;
		this.step = step;
		this.adding = adding;
		this.max = max;
	}

	/**
	 * 定額手数料を保持します。
	 */
	private double commission;

	/**
	 * 定額手数料を返します。
	 * 
	 * @return 定額手数料
	 */
	public double getCommission() { return commission; }

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

	/**
	 * 一段階あたりの値幅を保持します。
	 */
	private double step;

	/**
	 * 一段階あたりの値幅を返します。
	 * 
	 * @return 一段階あたりの値幅
	 */
	public double getStep() { return step; }

	/**
	 * 一段階あたりの値幅を設定します。
	 * 
	 * @param step 一段階あたりの値幅
	 */
	public void setStep(final double step) { this.step = step; }

	/**
	 * 一段階あたりの追加手数料を保持します。
	 */
	private double adding;

	/**
	 * 一段階あたりの追加手数料を返します。
	 * 
	 * @return 一段階あたりの追加手数料
	 */
	public double getAdding() { return adding; }

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

	/**
	 * 上限手数料を保持します。
	 */
	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 = commission;
		if (step != 0) {
			result = result + adding * Math.floor((price * quantity - getBase()) / step);
			if (max != 0 && result > max)
				result = max;
		}
		return result;// + getSlippage();
	}

}
