/*
このファイルの中身は、NTT オープンソースライセンス　バージョン 1.0（「本
契約」という）の適用を受けます。
本契約を遵守しない限り、このファイルを使用してはなりません。
本契約のコピーは、次のＵＲＬから入手できます。
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

本契約に基づき頒布されるソフトウェアは、現状のまま、明示又は黙示のあらゆ
る種類の保証なしで、頒布されます。本契約に基づく権利及び制限を律する特定
の文言については、本契約を参照してください。

「オリジナルコード」は、 NTT Cyber Space Laboratories Code です。 
「オリジナルコード」の「初期開発者」は、日本電信電話株式会社です。  
日本電信電話株式会社により創作された部分は、Copyright (C) 2004 
日本電信電話株式会社 です。
全ての権利が留保されます。 
「コントリビュータ」：_____________________________________ 


The contents of this file are subject to the NTT Opensource License
Version 1.0 (the License); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

Software distributed under the License is distributed on an AS IS
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is NTT Cyber Space Laboratories Code .

The Initial Developer of the Original Code is NIPPON TELEGRAPH AND 
TELEPHONE CORPORATION.
Portions created by the NIPPON TELEGRAPH AND TELEPHONE CORPORATION 
are Copyright (C) 2004 NIPPON TELEGRAPH AND TELEPHONE CORPORATION. 
All Rights Reserved.

Contributor(s) ______________________________________.
*/
package jp.co.ntt.lms.installer.core.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.MessageFormat;
import java.util.logging.Logger;

import jp.co.ntt.lms.installer.core.InstallerException;
import jp.co.ntt.lms.installer.core.InstallerValues;
import jp.co.ntt.lms.installer.util.LoggerUtil;
import jp.co.ntt.lms.installer.util.StringUtil;

/**
 * 標準入出力に関するユーティリティ・クラス。
 * @author T.Nishiki
 */
public class InstallerUiUtil {
	/**
	 * ログ出力オブジェクト。
	 */
	private static Logger _logger;

	/**
	 * スタティック・イニシャライザ。<br>
	 * ログ出力オブジェクトを取得します。
	 */
	static {
		_logger = LoggerUtil.getLogger(InstallerUiUtil.class);
	}

	/**
	 * メッセージキー：未入力の場合のデフォルト値を表示するメッセージ。
	 */
	public static final String KEY_OUTPUT_DEFALUT_VALUE
		= "common.input.defaultvalue";

	/**
	 * メッセージキー：入力プロンプト文字列。
	 */
	public static final String KEY_OUTPUT_PROMPT = "common.input.prompt";

	/**
	 * 標準入力（キーボード入力）から１行読み込みます。
	 * 標準入力にてEnterキー押されるまで待ち、
	 * Enterキーが押されたらその直前の文字列を取得します。
	 * @return 標準入力で入力されて１行。
	 * @throws InstallerException 読込に失敗した場合。
	 */
	public static String readLine() throws InstallerException {
		BufferedReader reader = null;
		String line = null;
		try {
			reader = new BufferedReader(new InputStreamReader(System.in));
			line = reader.readLine();
		}
		catch (Exception e) {
			LoggerUtil.throwable(_logger, e);
			throw new InstallerException(e);
		}
		// nullは空文字列として戻す。
		if (line == null) {
			line = "";
		}
		return line;
	}

	/**
	 * メッセージを出力します。
	 * メッセージ出力前後に改行します。<br>
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 */
	public static void outputMessageAsTitle(
			InstallerValues values, String key) {
		System.out.println();
		System.out.println("-----------------------------------------------");
		outputMessage(values, key, null, true);
	}

	/**
	 * メッセージを出力します。
	 * メッセージ出力前後に改行します。<br>
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 */
	public static void outputConfirmTitle(
			InstallerValues values, String key) {
		System.out.println();
		outputMessage(values, key, null, true);
	}

	/**
	 * メッセージを出力します。
	 * メッセージを出力後に改行しません。<br>
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 */
	public static void outputMessage(
			InstallerValues values, String key) {
		outputMessage(values, key, null, false);
	}

	/**
	 * メッセージを出力します。
	 * メッセージを出力後に改行しません。<br>
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @param messageParams メッセージ・パラメータ。
	 */
	public static void outputMessage(
			InstallerValues values, String key, Object[] messageParams) {
		outputMessage(values, key, messageParams, false);
	}

	/**
	 * メッセージを出力します。<br>
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @param newLine 出力後改行する場合はtrue、改行しない場合はfalseを渡します。
	 */
	public static void outputMessage(
			InstallerValues values, String key, boolean newLine) {
		outputMessage(values, key, null, newLine);
	}

	/**
	 * メッセージを出力します。<br>
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @param newLine 出力後改行する場合はtrue、改行しない場合はfalseを渡します。
	 * @param messageParams メッセージ・パラメータ。
	 */
	public static void outputMessage(
			InstallerValues values, String key,
			Object[] messageParams, boolean newLine) {
		String message = values.getMessage(key);
		// メッセージが取得でき、かつ、パラメータが渡されている場合、
		// メッセージ・フォーマット処理をしてから、出力
		if (messageParams != null && StringUtil.isEmpty(message) == false) {
			String outputMessage
				= MessageFormat.format(message, messageParams);
			System.out.print(outputMessage);
		}
		else {
			System.out.print(message);
		}
		if ( newLine ) {
			System.out.println();
		}
	}

	/**
	 * メッセージを出力します。
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @param variable メッセージに続けて表示する値。
	 */
	public static void outputConfirm(
			InstallerValues values, String key, String variable) {
		// メッセージ
		outputMessage(values, key);
		// プロンプト
		outputMessage(values, KEY_OUTPUT_PROMPT);
		// 値
		System.out.println(variable);
	}

	/**
	 * メッセージを出力します。
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @param messageParams メッセージ・パラメータ。
	 * @param variable メッセージに続けて表示する値。
	 */
	public static void outputConfirm(
			InstallerValues values, String key,
			Object[] messageParams, String variable) {
		// メッセージ
		outputMessage(values, key, messageParams);
		// プロンプト
		outputMessage(values, KEY_OUTPUT_PROMPT);
		// 値
		System.out.println(variable);
	}

	/**
	 * ユーザに入力を求めるプロンプトを表示し、入力した値を戻します。
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @return ユーザが入力した値、またはデフォルト値。
	 * @throws InstallerException 読込時に例外が発生した場合。
	 */
	public static String askUserInput(
			InstallerValues values, String key)
			throws InstallerException {
		// このメソッドの戻り値。
		String line = null;
		try {
			line = askUserInput(values, key, null, null);
		}
		catch (InstallerException e) {
			throw e;
		}
		catch (Exception e) {
			LoggerUtil.throwable(_logger, e);
			throw new InstallerException(e);
		}
		return line;
	}

	/**
	 * ユーザに入力を求めるプロンプトを表示し、入力した値を戻します。
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @param defaultValue 未入力の場合のデフォルト値。
	 *                      デフォルト値がない場合、nullまたは空文字列。
	 * @return ユーザが入力した値、またはデフォルト値。
	 * @throws InstallerException 読込時に例外が発生した場合。
	 */
	public static String askUserInput(
			InstallerValues values, String key, String defaultValue)
			throws InstallerException {
		// このメソッドの戻り値。
		String line = null;
		try {
			line = askUserInput(values, key, null, defaultValue);
		}
		catch (InstallerException e) {
			throw e;
		}
		catch (Exception e) {
			LoggerUtil.throwable(_logger, e);
			throw new InstallerException(e);
		}
		return line;
	}

	/**
	 * ユーザに入力を求めるプロンプトを表示し、入力した値を戻します。
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @param messageParams メッセージ・パラメータ。
	 * @param defaultValue 未入力の場合のデフォルト値。
	 *                      デフォルト値がない場合、nullまたは空文字列。
	 * @return ユーザが入力した値、またはデフォルト値。
	 * @throws InstallerException 読込時に例外が発生した場合。
	 */
	public static String askUserInput(
			InstallerValues values, String key,
			Object[] messageParams, String defaultValue)
			throws InstallerException {
		// このメソッドの戻り値。
		String line = null;
		try {
			outputPrompt(values, key, messageParams, defaultValue);
			line = InstallerUiUtil.readLine();
			// 未入力でデフォルト値がある場合、その値を採用
			if (StringUtil.isEmpty(line) == true
					&& StringUtil.isEmpty(defaultValue) == false) {
				line = defaultValue;
			}
		}
		catch (InstallerException e) {
			throw e;
		}
		catch (Exception e) {
			LoggerUtil.throwable(_logger, e);
			throw new InstallerException(e);
		}
		return line;
	}

	/**
	 * ユーザに入力を求めるプロンプトを表示し、入力した数値を戻します。
	 * 数値を入力されるまで繰り返し入力を求めます。
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @return ユーザが入力した数値。
	 * @throws InstallerException 読込時に例外が発生した場合。
	 */
	public static int askUserInputInteger(
		InstallerValues values, String key) throws InstallerException {

		int returnValue = 0;
		try {
			while (true) {
				String line = askUserInput(values, key);
				try {
					returnValue = Integer.parseInt(line);
				}
				catch (Exception e) {
					continue;
				}
				break;
			}
		}
		catch (InstallerException e) {
			throw e;
		}
		catch (Exception e) {
			LoggerUtil.throwable(_logger, e);
			throw new InstallerException(e);
		}
		return returnValue;
	}

	/**
	 * ユーザにyn入力を求めるプロンプトを表示し、入力した値を戻します。
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @return yが入力されればtrue、nが入力されればfalse。
	 * @throws InstallerException 読込時に例外が発生した場合。
	 */
	public static boolean askUserConfirm(
			InstallerValues values, String key)
			throws InstallerException {
		// このメソッドの戻り値。
		boolean confirm = false;
		try {
			System.out.println();
			while (true) {
				String confirmInputed
					= InstallerUiUtil.askUserInput( values, key );
				if (confirmInputed.equals("y")) {
					confirm = true;
					break;
				}
				if (confirmInputed.equals("n")) {
					confirm = false;
					break;
				}
			}
		}
		catch (InstallerException e) {
			throw e;
		}
		catch (Exception e) {
			LoggerUtil.throwable(_logger, e);
			throw new InstallerException(e);
		}
		return confirm;
	}

	/**
	 * ユーザにyn入力を求めるプロンプトを表示し、入力した値を戻します。
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @param messageParams メッセージ・パラメータ。
	 * @return yが入力されればtrue、nが入力されればfalse。
	 * @throws InstallerException 読込時に例外が発生した場合。
	 */
	public static boolean askUserConfirm(
			InstallerValues values, String key, Object[] messageParams)
			throws InstallerException {
		// このメソッドの戻り値。
		boolean confirm = false;
		try {
			System.out.println();
			while (true) {
				String confirmInputed = InstallerUiUtil.askUserInput(
					values, key, messageParams, null);
				if (confirmInputed.equals("y")) {
					confirm = true;
					break;
				}
				if (confirmInputed.equals("n")) {
					confirm = false;
					break;
				}
			}
		}
		catch (InstallerException e) {
			throw e;
		}
		catch (Exception e) {
			LoggerUtil.throwable(_logger, e);
			throw new InstallerException(e);
		}
		return confirm;
	}

	/**
	 * booleanを確認入力の文字列に変換します。<br>
	 * @param confirm 変換元の値。
	 * @return confirmがtrueならば&quot;y&quot;、falseならば&quot;n&quot;。
	 */
	public static String convertBoolToConfirmString(boolean confirm) {
		if ( confirm ) {
			return "y";
		}
		return "n";
	}

	/**
	 * 入力用プロンプトを表示します。<br>
	 * @param values インストーラ共通データ・オブジェクト。
	 * @param key 取得して表示するメッセージのキー文字列。
	 * @param messageParams メッセージ・パラメータ。
	 * @param defaultValue 未入力の場合のデフォルト値。
	 *                      デフォルト値がない場合、nullまたは空文字列。
	 */
	private static void outputPrompt(
			InstallerValues values, String key,
			Object[] messageParams, String defaultValue) {
		// メッセージを出力
		outputMessage(values, key, messageParams);
		// デフォルト値
		if (StringUtil.isEmpty(defaultValue) == false) {
			String message = values.getMessage(KEY_OUTPUT_DEFALUT_VALUE);
			Object[] formatFields = new Object[]{
				defaultValue
			};
			String defaultMessage = MessageFormat.format(message, formatFields);
			System.out.print(defaultMessage);
		}
		// プロンプト
		outputMessage(values, KEY_OUTPUT_PROMPT);
	}
}
