//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/** @file
 * SF互換パッド実装
 * @author Junpee
 */

#include "LampBasic.h"
#include "Input/Pad/SFPad.h"
#include "Input/Joystick/Joystick.h"
#include "Input/Pad/PS2Pad.h"

namespace Lamp{

//------------------------------------------------------------------------------
// 互換性チェック
bool SFPad::checkCompatibility(Joystick* joystick){
	// X軸、Y軸が必要
	if(!joystick->hasXAxis()){ return false; }
	if(!joystick->hasYAxis()){ return false; }
	// ボタンは8ボタン必要
	if(joystick->getButtonCount() < 8){ return false; }
	return true;
}
//------------------------------------------------------------------------------
// 生成、破棄
//------------------------------------------------------------------------------
// コンストラクタ
SFPad::SFPad(Joystick* joystick) :
	Pad(joystick), digitalBoundary_(0.6f){
	// 互換性チェック
	Assert(checkCompatibility(joystick_));
	// ボタンマップの初期化を戦略的に行う
	// 究極は名前ベースでのボタン割り振り？
	int buttonCount = joystick_->getButtonCount();
	if(PS2Pad::checkCompatibility(joystick_) &&
		(buttonCount == 12)){
		// PS2変換ケーブルパッド用割り振り
		buttonMap_[buttonA] = PS2Pad::buttonMaru;
		buttonMap_[buttonB] = PS2Pad::buttonBatu;
		buttonMap_[buttonX] = PS2Pad::buttonSankaku;
		buttonMap_[buttonY] = PS2Pad::buttonSikaku;
		buttonMap_[buttonL] = PS2Pad::buttonL1;
		buttonMap_[buttonR] = PS2Pad::buttonR1;
		buttonMap_[buttonStart] = PS2Pad::buttonStart;
		buttonMap_[buttonSelect] = PS2Pad::buttonSelect;
	}else if(PS2Pad::checkCompatibility(joystick_) &&
		(buttonCount == 16)){
		// スマートジョイパッド用割り振り
		buttonMap_[buttonA] = PS2Pad::buttonMaru;
		buttonMap_[buttonB] = PS2Pad::buttonBatu;
		buttonMap_[buttonX] = PS2Pad::buttonSankaku;
		buttonMap_[buttonY] = PS2Pad::buttonSikaku;
		buttonMap_[buttonL] = PS2Pad::buttonL1;
		buttonMap_[buttonR] = PS2Pad::buttonR1;
		buttonMap_[buttonStart] = PS2Pad::buttonSelect;
		buttonMap_[buttonSelect] = PS2Pad::buttonStart;
/* // コンフィグで対応するべきっぽい
	}else if(buttonCount == 11){
		// エレコムの11ボタンパッドと仮定する
		buttonMap_[buttonA] = 2;
		buttonMap_[buttonB] = 1;
		buttonMap_[buttonX] = 5;
		buttonMap_[buttonY] = 4;
		buttonMap_[buttonL] = 6;
		buttonMap_[buttonR] = 7;
		buttonMap_[buttonStart] = 10;
		buttonMap_[buttonSelect] = 8;
	}else if(buttonCount == 10){
		// サンワの10ボタンパッドと仮定する
		buttonMap_[buttonA] = 2;
		buttonMap_[buttonB] = 0;
		buttonMap_[buttonX] = 3;
		buttonMap_[buttonY] = 1;
		buttonMap_[buttonL] = 4;
		buttonMap_[buttonR] = 6;
		buttonMap_[buttonStart] = 9;
		buttonMap_[buttonSelect] = 8;
	}else if(buttonCount == 9){
		// エレコムの9ボタンパッドと仮定する
		buttonMap_[buttonA] = 2;
		buttonMap_[buttonB] = 1;
		buttonMap_[buttonX] = 5;
		buttonMap_[buttonY] = 4;
		buttonMap_[buttonL] = 6;
		buttonMap_[buttonR] = 7;
		buttonMap_[buttonStart] = 0;
		buttonMap_[buttonSelect] = 3;
	}else if(buttonCount == 8){
		// サンワの8ボタンパッドと仮定する
		buttonMap_[buttonA] = 2;
		buttonMap_[buttonB] = 0;
		buttonMap_[buttonX] = 3;
		buttonMap_[buttonY] = 1;
		buttonMap_[buttonL] = 4;
		buttonMap_[buttonR] = 6;
		buttonMap_[buttonStart] = 7;
		buttonMap_[buttonSelect] = 5;
//*/
	}else{
		// ボタンは前から、L、R、Start、Selectは後ろから割り振る
		for(int i = 0;i < 4; i++){ buttonMap_[i] = i; }
		int offset = buttonCount - 4;
		for(int i = 0;i < 4; i++){ buttonMap_[i + 4] = offset + i; }
	}
}
//------------------------------------------------------------------------------
// デストラクタ
SFPad::~SFPad(){
}
//------------------------------------------------------------------------------
// ボタンマップ
//------------------------------------------------------------------------------
// ボタンマップの変更
void SFPad::changeButtonMap(Button button, int id){
	Assert((button >= 0) && (button < maxButtonCount));
	if(buttonMap_[button] == id){ return; }
	int destinationID = buttonMap_[button];
	for(int i = 0; i < maxButtonCount; i++){
		if(buttonMap_[i] == id){ buttonMap_[i] = destinationID; }
	}
	buttonMap_[button] = id;
}
//------------------------------------------------------------------------------
// 軸データの取得
//------------------------------------------------------------------------------
// X軸の取得
float SFPad::getXAxis() const{
	return joystick_->getXAxis();
}
//------------------------------------------------------------------------------
// Y軸の取得
float SFPad::getYAxis() const{
	return joystick_->getYAxis();
}
//------------------------------------------------------------------------------
// 十字キーデータの取得
//------------------------------------------------------------------------------
// 上キーが押されているか
bool SFPad::upKeyPressed() const{
	return yAxisToUpKey(joystick_->getYAxis());
}
//------------------------------------------------------------------------------
// 上キーが下がった
bool SFPad::upKeyDown() const{
	return (yAxisToUpKey(joystick_->getYAxis()) &&
		(!yAxisToUpKey(joystick_->getPreYAxis())));
}
//------------------------------------------------------------------------------
// 上キーが上がった
bool SFPad::upKeyUp() const{
	return (!yAxisToUpKey(joystick_->getYAxis()) &&
		(yAxisToUpKey(joystick_->getPreYAxis())));
}
//------------------------------------------------------------------------------
// 下キーが押されているか
bool SFPad::downKeyPressed() const{
	return yAxisToDownKey(joystick_->getYAxis());
}
//------------------------------------------------------------------------------
// 下キーが下がった
bool SFPad::downKeyDown() const{
	return (yAxisToDownKey(joystick_->getYAxis()) &&
		(!yAxisToDownKey(joystick_->getPreYAxis())));
}
//------------------------------------------------------------------------------
// 下キーが上がった
bool SFPad::downKeyUp() const{
	return (!yAxisToDownKey(joystick_->getYAxis()) &&
		(yAxisToDownKey(joystick_->getPreYAxis())));
}
//------------------------------------------------------------------------------
// 左キーが押されているか
bool SFPad::leftKeyPressed() const{
	return xAxisToLeftKey(joystick_->getXAxis());
}
//------------------------------------------------------------------------------
// 左キーが下がった
bool SFPad::leftKeyDown() const{
	return (xAxisToLeftKey(joystick_->getXAxis()) &&
		(!xAxisToLeftKey(joystick_->getPreXAxis())));
}
//------------------------------------------------------------------------------
// 左キーが上がった
bool SFPad::leftKeyUp() const{
	return (!xAxisToLeftKey(joystick_->getXAxis()) &&
		(xAxisToLeftKey(joystick_->getPreXAxis())));
}
//------------------------------------------------------------------------------
// 右キーが押されているか
bool SFPad::rightKeyPressed() const{
	return xAxisToRightKey(joystick_->getXAxis());
}
//------------------------------------------------------------------------------
// 右キーが下がった
bool SFPad::rightKeyDown() const{
	return (xAxisToRightKey(joystick_->getXAxis()) &&
		(!xAxisToRightKey(joystick_->getPreXAxis())));
}
//------------------------------------------------------------------------------
// 右キーが上がった
bool SFPad::rightKeyUp() const{
	return (!xAxisToRightKey(joystick_->getXAxis()) &&
		(xAxisToRightKey(joystick_->getPreXAxis())));
}
//------------------------------------------------------------------------------
// ボタンデータの取得
//------------------------------------------------------------------------------
// ボタンが押されているか
bool SFPad::buttonPressed(Button button) const{
	Assert((button >= 0) && (button < maxButtonCount));
	return joystick_->buttonPressed(buttonMap_[button]);
}
//------------------------------------------------------------------------------
// ボタンが下がった
bool SFPad::buttonDown(Button button) const{
	Assert((button >= 0) && (button < maxButtonCount));
	return joystick_->buttonDown(buttonMap_[button]);
}
//------------------------------------------------------------------------------
// ボタンが上がった
bool SFPad::buttonUp(Button button) const{
	Assert((button >= 0) && (button < maxButtonCount));
	return joystick_->buttonUp(buttonMap_[button]);
}
//------------------------------------------------------------------------------
// 文字列データ取得
//------------------------------------------------------------------------------
// ボタン文字列の取得
String SFPad::getButtonString(Button button){
	if(button == -1){ return "Unknown"; }
	Assert((button >= 0) && (button < maxButtonCount));
	String buttonString[] = { "A", "B", "X", "Y", "L", "R", "Start", "Select" };
	return buttonString[button];
}
//------------------------------------------------------------------------------
// 文字列への変換
String SFPad::toString() const{
	String result, temp;
	result = Pad::toString();

	// 十字キー
	result += "          Press Down   Up\n";
	temp.format(" UpKey        %d    %d    %d\n",
		upKeyPressed(), upKeyDown(), upKeyUp());
	result += temp;
	temp.format(" DownKey      %d    %d    %d\n",
		downKeyPressed(), downKeyDown(), downKeyUp());
	result += temp;
	temp.format(" LeftKey      %d    %d    %d\n",
		leftKeyPressed(), leftKeyDown(), leftKeyUp());
	result += temp;
	temp.format(" RightKey     %d    %d    %d\n",
		rightKeyPressed(), rightKeyDown(), rightKeyUp());
	result += temp;

	// ボタン
	temp.format(" A            %d    %d    %d\n",
		buttonPressed(buttonA), buttonDown(buttonA), buttonUp(buttonA));
	result += temp;
	temp.format(" B            %d    %d    %d\n",
		buttonPressed(buttonB), buttonDown(buttonB), buttonUp(buttonB));
	result += temp;
	temp.format(" X            %d    %d    %d\n",
		buttonPressed(buttonX), buttonDown(buttonX), buttonUp(buttonX));
	result += temp;
	temp.format(" Y            %d    %d    %d\n",
		buttonPressed(buttonY), buttonDown(buttonY), buttonUp(buttonY));
	result += temp;
	temp.format(" L            %d    %d    %d\n",
		buttonPressed(buttonL), buttonDown(buttonL), buttonUp(buttonL));
	result += temp;
	temp.format(" R            %d    %d    %d\n",
		buttonPressed(buttonR), buttonDown(buttonR), buttonUp(buttonR));
	result += temp;
	temp.format(" Start        %d    %d    %d\n",
		buttonPressed(buttonStart), buttonDown(buttonStart),
		buttonUp(buttonStart));
	result += temp;
	temp.format(" Select       %d    %d    %d\n",
		buttonPressed(buttonSelect), buttonDown(buttonSelect),
		buttonUp(buttonSelect));
	result += temp;
	return result;
}
//------------------------------------------------------------------------------
} // End of namespace Lamp
//------------------------------------------------------------------------------
