/*
 * The MIT License
 *
 * Copyright 2013 Dra0211.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package kinugasa.inputDevice;

/**
 * ゲームパッドへの接続を確立し、状態を取得します.
 * <br>
 *
 * <br>
 *
 * @version 1.0.0 - 2013/01/14_13:18:05<br>
 * @author Dra0211<br>
 */
public final class GamePadConnection {

	/**
	 * このクラスはユーティリティクラスです.インスタンス化できません.
	 * <br>
	 */
	private GamePadConnection() {
	}

	/**
	 * ゲームパッドの状態をkgp.dllを使用して検査し、GamePadState構造体として返します.
	 * <Br>
	 *
	 * @param index 検査するゲームパッドのインデックス.通常は接続順またはUSBのポート順に割り振られます.<br>
	 *
	 * @return 指定したインデックスのゲームパッドの状態を返します.そのインデックスのゲームパッドが接続されていない
	 * 場合は、接続状態が[false]のGamePadStateを返します。その場合、接続状態以外のステータスは初期値(falseまたは0）
	 * に設定されます.<br>
	 */
	public static GamePadState getState(PlayerIndex index) {
		return getState(index.getValue());
	}

	/**
	 * ゲームパッドの状態をkgp.dllを使用して検査し、GamePadState構造体として返します.
	 * <Br>
	 *
	 * @param index 検査するゲームパッドのインデックス.通常は接続順またはUSBのポート順に割り振られます.<br>
	 *
	 * @return 指定したインデックスのゲームパッドの状態を返します.そのインデックスのゲームパッドが接続されていない
	 * 場合は、接続状態が[false]のGamePadStateを返します。その場合、接続状態以外のステータスは初期値(falseまたは0）
	 * に設定されます.<br>
	 */
	public static GamePadState getState(int index) {
		return new GamePadState(getNativeState(index));
	}

	/**
	 * 全ての状態が初期値のGamePadStateを返します.
	 *
	 * @return 全ての状態が初期値で、接続されていないGamePadState.<br>
	 */
	public static GamePadState createClearState() {
		return CLEAR_STATE;
	}

	/**
	 * kgp.dllを使用してゲームパッド状態のネイティブな値を取得します.
	 * <br>
	 * このメソッドは、GamePadStateを構築する必要がないため、getState(PlaerIndex)よりも
	 * 高速に動作します。ただし、このメソッドで得られる状態は整形されていないため、
	 * 通常はgetStateを使用してください。<br>
	 * このメソッドはJNIを使用します。/kgp.dllがロードされていない場合、このメソッドは使用できません。
	 * kgp.dllはDllLoaderクラスの静的初期化ブロックでロードされます。<br>
	 * <br>
	 * このメソッドで得られる状態は、以下のフォーマットです。<br>
	 * <br>
	 * [BUTTON_A(0)]から[BUTTON_BACK(13)]までは、
	 * デジタルボタンの状態が格納されています。<br>
	 * このステータスは、ボタンが押されていない場合にNATIVE_FALSEと同値になります。
	 * 押されている場合はNATIVE_FALSEでない値が格納されます。<br>
	 * <Br>
	 * [TRIGGER_LEFT]および[TRIGGER_RIGHT]には、アナログトリガーの値が格納されています。<Br>
	 * この値は、トリガーの押し込みによって0.0fから1.0まで連続的に変化します。デッドゾーンは定義されていません。<br>
	 * <br>
	 * [THUMB_STICK_LEFT_X]、[THUMB_STICK_LEFT_Y]、[THUMB_STICK_RIGHT_X]、[THUMB_STICK_RIGHT_Y]には、アナログスティック
	 * の値が格納されています。この値は、スティックの傾きによって-1.0fから1.0fの間で連続的に変化し、
	 * X軸では左側、Y軸では下側が最低の値となります。スティックを操作していない場合は、XおよびYの値が0になります。<br>
	 * スティックの動作範囲は通常円形なので、スティックを「左下」や「右上」に最大まで傾けた場合、
	 * XおよびYの値がどちらも最大値または最低値になることはありません。<br>
	 * デッドゾーンは定義されていません。<br>
	 * <br>
	 * [CONNECTION]には、このゲームパッドの接続状態が格納されています。<br>
	 * この値は、接続されていなければNATIVE_FALSEと同値になります。<br>
	 * <br>
	 * <br>
	 * 以下にインデックスおよびデータの例を示します。<br>
	 * <br>
	 * <table border="1">
	 *
	 * <tr>
	 * <th>
	 * インデックス
	 * </th>
	 * <th>
	 * インデックスの定数
	 * </th>
	 * <th>
	 * 定義される状態
	 * </th>
	 * <th>
	 * 値の有効範囲
	 * </th>
	 * <th>
	 * 初期値
	 * </th>
	 * </tr>
	 *
	 * <tr>
	 * <th>
	 * 0から13
	 * </th>
	 * <th>
	 * BUTTON_AからBUTTON_BACK
	 * </th>
	 * <th>
	 * それぞれのボタン定数のインデックスにボタンの状態が格納される<br>
	 * </th>
	 * <th>
	 * NATIVE_FALSEかそれ以外の値
	 * </th>
	 * <th>
	 * NATIVE_FALSE
	 * </th>
	 * </tr>
	 *
	 * <tr>
	 * <th>
	 * 14、15
	 * </th>
	 * <th>
	 * TRIGGER_LEFT、TRIGGER_RIGHT
	 * </th>
	 * <th>
	 * アナログトリガーの値が格納される
	 * </th>
	 * <th>
	 * 0.0fから1.0fまで可変
	 * </th>
	 * <th>
	 * 0.0f
	 * </th>
	 * </tr>
	 *
	 * <tr>
	 * <th>
	 * 16、17、18、19
	 * </th>
	 * <th>
	 * THUMB_STICK_LEFT_X、THUMB_STICK_LEFT_Y、<br>THUMB_STICK_RIGHT_X、THUMB_STICK_RIGHT_Y
	 * </th>
	 * <th>
	 * サムスティックの値が格納される<Br>スティックの位置が中央のときXおよびYが0になり、<br>
	 * 右上が正の値、左下が負の値になる
	 * </th>
	 * <th>
	 * -1.0fから1.0fまで可変
	 * </th>
	 * <th>
	 * 0.0f
	 * </th>
	 * </tr>
	 *
	 * <tr>
	 * <th>
	 * 20
	 * </th>
	 * <th>
	 * CONNECTION
	 * </th>
	 * <th>
	 * ゲームパッドの接続状態が格納される<br>接続されている場合、NATIVE_TRUEと同値になる
	 * </th>
	 * <th>
	 * NATIVE_FALSEかそれ以外の値
	 * </th>
	 * <th>
	 * NATIVE_FALSE
	 * </th>
	 * </tr>
	 *
	 * </table>
	 *
	 * @param playerIndex 検査するゲームパッドのインデックスを送信します。ゲームパッドは、通常4台まで接続できます。
	 * 負の値等不正なインデックスを送信しても例外は発生せず、「接続されていない」状態が返されます.<Br>
	 *
	 * @return 指定したインデックスのゲームパッドの状態が返されます.<br>
	 */
	public static native float[] getNativeState(int playerIndex);
	//
	/**
	 * kgp.dllによって返される、配列の長さです.
	 * この値は、getNativeState(int)で返される配列の要素数(length)と一致します。 */
	public static final int LENGTH = 21;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_A = 0;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_B = 1;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_X = 2;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_Y = 3;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_LB = 4;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_RB = 5;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_LEFT_STICK = 6;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_RIGHT_STICK = 7;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_PAD_UP = 8;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_PAD_DOWN = 9;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_PAD_LEFT = 10;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_PAD_RIGHT = 11;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_START = 12;
	/** これらの値はゲームパッドのデジタルボタンを識別します. */
	public static final int BUTTON_BACK = 13;
	/** ゲームパッドのアナログトリガーを識別します. */
	public static final int TRIGGER_LEFT = 14;
	/** ゲームパッドのアナログトリガーを識別します. */
	public static final int TRIGGER_RIGHT = 15;
	/** ゲームパッドのアナログスティックを識別します. */
	public static final int THUMB_STICK_LEFT_X = 16;
	/** ゲームパッドのアナログスティックを識別します. */
	public static final int THUMB_STICK_LEFT_Y = 17;
	/** ゲームパッドのアナログスティックを識別します. */
	public static final int THUMB_STICK_RIGHT_X = 18;
	/** ゲームパッドのアナログスティックを識別します. */
	public static final int THUMB_STICK_RIGHT_Y = 19;
	/** ゲームパッドの識別状態が格納されている場所のインデックスです. */
	public static final int CONNECTION = 20;
	//
	/** kgp.dllによって定義される、ネイティブな「FALSE」の状態です. */
	public static final int NATIVE_FALSE = 0;
	/** kgp.dllによって使用される、トリガーの入力の最小値です. */
	public static final int TRIGGER_MIN = 0;
	/** kgp.dllによって使用される、トリガーの入力の最大値です. */
	public static final int TRIGGER_MAX = 255;
	/** kgp.dllによって使用される、スティックの入力の最小値です. */
	public static final int THUMBSTICK_MIN = Short.MIN_VALUE;
	/** kgp.dllによって使用される、トリガーの入力のデフォルト値です. */
	public static final int THUMBSTICK_CENTER = 0;
	/** kgp.dllによって使用される、スティックの入力の最大値です. */
	public static final int THUMBSTICK_MAX = Short.MAX_VALUE;
	/** kgp.dllによって使用される、トリガーの入力の最小値からの最大値までの絶対値です. */
	public static final int THUMSTICK_ABS_MAX = 65534;
	/** 全ての状態が初期値のGamePadStateです. */
	private static final GamePadState CLEAR_STATE = new GamePadState(new float[LENGTH]);
}
