//
// CopyRight (C) 2002, IPA, eLC, NTT Resonant Inc. All rights reserved.
//
//	Duration
//
//	変更履歴
//		2002.12.25  新規作成
//

package jp.co.ntt.lms.lo.scorm.kernel;

import java.text.DecimalFormat;
import jp.co.ntt.lms.lo.scorm.kernel.exception.SystemException;

/**
 *	Durationクラス<BR>
 * 	期間情報を生成取得するクラス<BR>
 */
public class Duration {

	/** ミリ秒 */
	private long msec;

	/**
	 * コンストラクタ
	 *
	 * 	@param
	 *		duration	期間を表す文字列
	 *					書式：PxxYxxMxxDTxxHxxMxx.xS
	 *							P〜:年月日
	 *								xxY:年、xxM:月、xxD:日
	 *							T〜：時間
	 *								xxH:時間、xxM:分、xx.xS:秒
	 *							xx:任意の数字
	 */
	public Duration(String duration) throws SystemException {

		try {

			this.msec = parse(duration);

		}
		catch (Exception e) {
			throw new SystemException("Duration[Duration(String duration)]: '" + duration + "' のDurationを作れません。");
		}
	}

	/**
	 *	コンストラクタ<BR>
	 *
	 *   @param	msec	期間(ミリ秒単位)
	 *
	 */
	public Duration(long msec) {
		this.msec = msec;
	}

	/**
	 *	コンストラクタ<BR>
	 *
	 * @param	duration	期間
	 *
	 */
	public Duration(Duration duration) {
		this.msec = duration.msec;
	}

	/**
	 * msecの時間を追加する
	 *
	 *	@param
	 *		msec	追加する時間(ミリ秒)
	 */
	public Duration add(long msec) {
		return new Duration(this.msec + msec);
	}

	/**
	 * durationの期間を追加する
	 *
	 *	@param
	 *		duration	追加する期間
	 */
	public Duration add(Duration duration) {
		return new Duration(this.msec + duration.msec);
	}

	/**
	 *	String型文字列のmsecを変換して加算する
	 *
	 * 	@param msec 加算するmsec
	 */
	public Duration add(String msec) {
		return new Duration(this.msec + Long.parseLong(msec));
	}

	/**
	* 時間を取得する
	*
	* 	@return long ミリ秒を取得する
	*/
	public long getMsec() {
		return msec;
	}

	/**
	 * 現在の期間と任意の期間との長さを比べる
	 *	@param
	 *		val		比較する期間
	 *	@return
	 *		 1		現在の期間の方が任意の期間より長い
	 *		 0		現在の期間と任意の期間が同じ長さ
	 *		-1		現在の期間の方が任意の期間より短い
	 */
	public int compareTo(Duration val) {

		long compareDuration = val.getMsec();

		if (this.msec > compareDuration) {
			return 1;
		}
		else if (this.msec == compareDuration) {
			return 0;
		}
		else {
			return -1;
		}
	}

	/** "999"へフォーマットする為のDecimalFormat */
	private static DecimalFormat _999Formatter = new DecimalFormat("000");

	/**
	 *  期間を秒単位に変換
	 *
	 *	@return	期間を秒単位に変換した文字列
	 */
	public String toString() {
		StringBuffer sb = new StringBuffer();

		sb.append("PT");
		sb.append(Long.toString(msec / 1000));
		sb.append(".");
		sb.append(_999Formatter.format(msec % 1000));
		sb.append("S");

		return sb.toString();
	}

	/**
	 * フォーマットの変換<BR>
	 * duration 文字列からフォーマットを調べる<BR>
	 * フォーマット形式を以下の方法で場合分けする<BR>
	 * ・文字列の先頭に 'P' がある              ・・・ PxxYxxMxxDTxxHxxMxx.xS<BR>
	 * ・それ以外の場合                         ・・・ HHHH:MM:SS.SS<BR>
	 * @param duration duration文字列<BR>
	 * @return durationのミリ秒表現<BR>
	 */
	private long parse(String duration) throws Exception {

		//計算
		String p_dur = "";
		String t_dur = "";
		String str_year = "";
		String str_month = "";
		String str_day = "";
		String str_hour = "";
		String str_min = "";
		String str_sec = "";
		String buf = "";
		int t_dur_st = duration.indexOf("T");
		long year = 0L;
		long month = 0L;
		long day = 0L;
		long hour = 0L;
		long min = 0L;
		double sec = 0.0;
		long msec;

		// durationを年月日と時間に分ける
		if (t_dur_st != -1) {
			p_dur = duration.substring(0, t_dur_st);
			t_dur = duration.substring(t_dur_st);
		}
		else {
			p_dur = duration.substring(0);
		}

		// 年月日を取得
		if (!p_dur.equals("")) {
			buf = p_dur.substring(1);
			if (buf.indexOf("Y") != -1) {
				str_year = buf.substring(0, buf.indexOf("Y"));
				year = Long.parseLong(str_year);
				year = year * 365L * 24L;
				year = year * 60L * 60L;
				year = year * 1000L;
				buf = buf.substring(buf.indexOf("Y") + 1);
			}
			if (buf.indexOf("M") != -1) {
				str_month = buf.substring(0, buf.indexOf("M"));
				month = Long.parseLong(str_month);
				month = month * 31L * 24L;
				month = month * 60L * 60L;
				month = month * 1000L;
				buf = buf.substring(buf.indexOf("M") + 1);
			}
			if (buf.indexOf("D") != -1) {
				str_day = buf.substring(0, buf.indexOf("D"));
				day = Long.parseLong(str_day);
				day = day * 24L;
				day = day * 60L * 60L;
				day = day * 1000L;
			}
		}
		// 時間、分、秒を取得
		if (!t_dur.equals("")) {
			buf = t_dur.substring(1);
			if (buf.indexOf("H") != -1) {
				str_hour = buf.substring(0, buf.indexOf("H"));
				hour = Long.parseLong(str_hour);
				hour = hour * 60L * 60L;
				hour = hour * 1000L;
				buf = buf.substring(buf.indexOf("H") + 1);
			}
			if (buf.indexOf("M") != -1) {
				str_min = buf.substring(0, buf.indexOf("M")); // 分取得
				min = Long.parseLong(str_min);
				min = min * 60L * 1000L;
				buf = buf.substring(buf.indexOf("M") + 1);
			}
			if (buf.indexOf("S") != -1) {
				str_sec = buf.substring(0, buf.indexOf("S"));
				sec = Double.parseDouble(str_sec);
				sec = sec * 1000L;
			}
		}

		msec = (long) (year + month + day + hour + min + sec);

		return msec;
	}
}
