package jp.ne.mki.wedge.rule.client.component.frame;

import java.awt.event.KeyEvent;

import javax.swing.AbstractButton;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.plaf.ComponentInputMapUIResource;

import jp.ne.mki.wedge.rule.base.AbstractClient;
import jp.ne.mki.wedge.run.client.data.Item;

/**
 *   <h2>ボタンにFunctionKeyのKeyMap追加</h2>
 *   <p>In(0)に指定されたアイテムのボタンコンポーネント)に対して、画面にフォーカスが当たっているとき(JComponent.WHEN_IN_FOCUSED_WINDOW)のInputMapにパラメータで指定された
 *      キーを、追加(put)します。<br>
 *    この設定により、ショートカットキーの登録が行えます。但し、Modifierの登録は行えません。ModifierをAltにしたい場合にはニーモニックキーを使用してください。<br>
 *      このロジッククラスでは、InputMapに対してPutのみ行います。このロジッククラス実行後、InputMapのクリアが行われる処理(ニーモニックの再登録など)が
 *      行われるとこの設定はクリアされますのでご注意ください。<br>
 *    KeyMap出来るボタンコンポーネントは一つのみになります</p>
 * <br/>
 * <h4>[I/O RECORD]</h4>
 * <table border="1" cellpadding="3" cellspacing="0" width="100%">
 *  <tr class="TableSubHeadingColor">
 *      <th style="width:50%;">InputRecord</th>
 *      <th>OutputRecord</th>
 *  </tr><tr class="TableRowColor">
 *      <td>
 *      <!--  InputRecordの内容を記述   -->
 *          設定するボタンコンポーネントが割り当てられたアイテム(一つ)
 *      <!--  ここまで   -->
 *      </td>
 *      <td>
 *      <!-- OutputRecordの内容を記述    -->
 *
 *      <!--  ここまで   -->
 *      </td>
 *  </tr></table>
 *
 * <h4>[RULE PARAMETER]</h4>
 * <table border="1" cellpadding="3" cellspacing="0" width="100%">
 *  <tr>
 *      <th style="width:100px;" class="TableSubHeadingColor">Parameter</th>
 *      <td class="TableRowColor">
 *      <!-- Parameterの内容を記述    -->
 *          ファンクションキーの名称(F1,F2・・・)
 *      <!--ここまで   -->
 *      </td>
 *  </tr></table>
 *
 * @author mki
 * @version 1.0
 */

public class SetFunctionKeyMapToButton extends AbstractClient {

	AbstractButton button = null;
	int keyId = -1;
	/**
	 * IOパラメータ取得。{@link #execute() execute} の前に実行される。
	 * @return int OK=処理続行、ERROR=異常終了、CANCEL=処理を中断(正常終了)
	 */
	public int getIOParameter()   {
		//入力引数より、対象のボタンコンポーネント取得
		Item data = getInItem(0);
		if (data == null) {
			setErrorMessageMustInRecord(1);
			return IO_ERROR_IN;
		}
		JComponent comp = data.getComponent();
		if (comp instanceof AbstractButton) {
			button = (AbstractButton) comp;
		} else {
			setErrorMessageMustInComp(1, "AbstractButton");
			return IO_ERROR_IN;
		}

		//パラメータよりKeyID取得
		try {
			keyId = getFunctionKeyNo(getRuleParameter());
		} catch (Exception ex) {
			errorMessage = ex.getMessage();
			return IO_ERROR_PARAMETER;
		}
		return OK;
	}

	/**
	 * ロジッククラスの処理を実行します
	 * @return int OK
	 */
	public int execute() {

		setKeyMap(keyId, button);
		return OK;
	}

	/**
	 * ボタンコンポーネントにKeyMapを行います
	 * @param int Key番号
	 * @param AbstractButton 割り当てるボタン
	 */
	protected static void setKeyMap(int key, AbstractButton button) {
		if (button == null) {
			return;
		}
		if (key < 0) {
			return;
		}
		InputMap map = SwingUtilities.getUIInputMap(button, JComponent.WHEN_IN_FOCUSED_WINDOW);

		if (map == null) {
			map = new ComponentInputMapUIResource(button);
			SwingUtilities.replaceUIInputMap(button, JComponent.WHEN_IN_FOCUSED_WINDOW, map);
		}

		if (map != null) {
			map.put(KeyStroke.getKeyStroke(key, 0, false), "pressed");
			map.put(KeyStroke.getKeyStroke(key, 0, true), "released");
		}

	}
	/**
	 * ファンクションの文字列からキー番号を取得します
	 * @param String ファンクションキー文字列
	 * @return int キー番号
	 */
	protected static int getFunctionKeyNo(String keyString) throws Exception {
		if (keyString.equals("F1")) {
			return KeyEvent.VK_F1;
		} else if (keyString.equals("F2")) {
			return KeyEvent.VK_F2;
		} else if (keyString.equals("F3")) {
			return KeyEvent.VK_F3;
		} else if (keyString.equals("F4")) {
			return KeyEvent.VK_F4;
		} else if (keyString.equals("F5")) {
			return KeyEvent.VK_F5;
		} else if (keyString.equals("F6")) {
			return KeyEvent.VK_F6;
		} else if (keyString.equals("F7")) {
			return KeyEvent.VK_F7;
		} else if (keyString.equals("F8")) {
			return KeyEvent.VK_F8;
		} else if (keyString.equals("F9")) {
			return KeyEvent.VK_F9;
		} else if (keyString.equals("F10")) {
			return KeyEvent.VK_F10;
		} else if (keyString.equals("F11")) {
			return KeyEvent.VK_F11;
		} else if (keyString.equals("F12")) {
			return KeyEvent.VK_F12;
		} else {
			return Integer.parseInt(keyString);
		}
	}

	/**
	 * 終了処理。保持していた変数などを開放する処理を記述します。<br/>
	 * {@link #execute() execute} の後に実行されます。<br/>正常終了・異常終了などに関わらず必ず実行されます。
	 */
	public void exit() {
		button = null;
	}
}