package org.cocos2dx.lib;

import org.cocos2dx.lib.GameControllerDelegate;

import android.content.Context;
import android.os.Handler;
import android.util.SparseIntArray;

import com.bda.controller.Controller;
import com.bda.controller.ControllerListener;
import com.bda.controller.KeyEvent;
import com.bda.controller.MotionEvent;
import com.bda.controller.StateEvent;

public class GameControllerMoga implements ControllerListener, GameControllerDelegate {

	private static final String mVendorName = "Moga";
	
	private float mOldLeftThumbstickX = 0.0f;
	private float mOldLeftThumbstickY = 0.0f;
	private float mOldRightThumbstickX = 0.0f;
	private float mOldRightThumbstickY = 0.0f;
	
	private float mOldLeftTrigger = 0.0f;
	private float mOldRightTrigger = 0.0f;

	private SparseIntArray mKeyMap = null;

	public GameControllerMoga() {
		mKeyMap = new SparseIntArray(20);
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_A, GameControllerDelegate.BUTTON_A);
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_B, GameControllerDelegate.BUTTON_B);
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_X, GameControllerDelegate.BUTTON_X);
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_Y, GameControllerDelegate.BUTTON_Y);
		
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_L1,
				GameControllerDelegate.BUTTON_LEFT_SHOULDER);
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_R1,
				GameControllerDelegate.BUTTON_RIGHT_SHOULDER);
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_L2,
				GameControllerDelegate.BUTTON_LEFT_TRIGGER);
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_R2,
				GameControllerDelegate.BUTTON_RIGHT_TRIGGER);
		
		mKeyMap.put(KeyEvent.KEYCODE_DPAD_UP,
				GameControllerDelegate.BUTTON_DPAD_UP);
		mKeyMap.put(KeyEvent.KEYCODE_DPAD_DOWN,
				GameControllerDelegate.BUTTON_DPAD_DOWN);
		mKeyMap.put(KeyEvent.KEYCODE_DPAD_LEFT,
				GameControllerDelegate.BUTTON_DPAD_LEFT);
		mKeyMap.put(KeyEvent.KEYCODE_DPAD_RIGHT,
				GameControllerDelegate.BUTTON_DPAD_RIGHT);
		
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_START,
				GameControllerDelegate.BUTTON_START);
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_SELECT,
				GameControllerDelegate.BUTTON_SELECT);
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_START,
				GameControllerDelegate.BUTTON_START);
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_THUMBL,
				GameControllerDelegate.BUTTON_LEFT_THUMBSTICK);
		mKeyMap.put(KeyEvent.KEYCODE_BUTTON_THUMBR,
				GameControllerDelegate.BUTTON_RIGHT_THUMBSTICK);
	}
	
	public void onKeyEvent(KeyEvent event) {		
		int keycode = event.getKeyCode();
		if (keycode == KeyEvent.KEYCODE_BUTTON_L2
				|| keycode == KeyEvent.KEYCODE_BUTTON_R2) {
			return;
		}
		boolean isPressed = event.getAction() == KeyEvent.ACTION_DOWN;
		boolean isAnalog = false;

		if (keycode == KeyEvent.KEYCODE_BUTTON_THUMBL
				|| keycode == KeyEvent.KEYCODE_BUTTON_THUMBR) {
			isAnalog = true;
		}

		if (mKeyMap.get(keycode, Integer.MIN_VALUE) != Integer.MIN_VALUE && mControllerEventListener != null) {
			mControllerEventListener.onButtonEvent(mVendorName,
					event.getControllerId(), mKeyMap.get(keycode), isPressed,
					isPressed ? 1.0f : 0.0f, isAnalog);
		}
	}

	@Override
	public void onMotionEvent(MotionEvent event) {
		if (mControllerEventListener == null) {
			return;
		}
		int controllerId = event.getControllerId();
		
		float newLeftThumbstickX = event.getAxisValue(MotionEvent.AXIS_X);
		if (newLeftThumbstickX != mOldLeftThumbstickX) {
			mControllerEventListener.onAxisEvent(mVendorName,
					controllerId,
					GameControllerDelegate.THUMBSTICK_LEFT_X,
					newLeftThumbstickX, true);
			mOldLeftThumbstickX = newLeftThumbstickX;
		}

		float newLeftThumbstickY = event.getAxisValue(MotionEvent.AXIS_Y);
		if (newLeftThumbstickY != mOldLeftThumbstickY) {
			mControllerEventListener.onAxisEvent(mVendorName,
					controllerId,
					GameControllerDelegate.THUMBSTICK_LEFT_Y,
					newLeftThumbstickY, true);
			mOldLeftThumbstickY = newLeftThumbstickY;
		}

		float newRightThumbstickX = event.getAxisValue(MotionEvent.AXIS_Z);
		if (newRightThumbstickX != mOldRightThumbstickX) {
			mControllerEventListener.onAxisEvent(mVendorName,
					controllerId,
					GameControllerDelegate.THUMBSTICK_RIGHT_X,
					newRightThumbstickX, true);
			mOldRightThumbstickX = newRightThumbstickX;
		}

		float newRightThumbstickY = event.getAxisValue(MotionEvent.AXIS_RZ);
		if (newRightThumbstickY != mOldRightThumbstickY) {
			mControllerEventListener.onAxisEvent(mVendorName,
					controllerId,
					GameControllerDelegate.THUMBSTICK_RIGHT_Y,
					newRightThumbstickY, true);
			mOldRightThumbstickY = newRightThumbstickY;
		}
		
		float newLeftTrigger = event.getAxisValue(MotionEvent.AXIS_LTRIGGER);
		if (newLeftTrigger != mOldLeftTrigger) {
			mControllerEventListener.onAxisEvent(mVendorName,
					controllerId,
					GameControllerDelegate.BUTTON_LEFT_TRIGGER,
					newLeftTrigger, true);
			mOldLeftTrigger = newLeftTrigger;
		}
		
		float newRightTrigger = event.getAxisValue(MotionEvent.AXIS_RTRIGGER);
		if (newRightTrigger != mOldRightTrigger) {
			mControllerEventListener.onAxisEvent(mVendorName,
					controllerId,
					GameControllerDelegate.BUTTON_RIGHT_TRIGGER,
					newRightTrigger, true);
			mOldRightTrigger = newRightTrigger;
		}
	}

	@Override
	public void onStateEvent(StateEvent event) {
		if (mControllerEventListener != null) {
			switch (event.getState()) {
			case StateEvent.STATE_CONNECTION:
				switch (event.getAction()) {
				case StateEvent.ACTION_DISCONNECTED:
					// disconnected from controller
					mControllerEventListener.onDisconnected(mVendorName,
							event.getControllerId());
					break;
				case StateEvent.ACTION_CONNECTED:
					// connected to controller
					mControllerEventListener.onConnected(mVendorName,
							event.getControllerId());
					break;
				case StateEvent.ACTION_CONNECTING:
					// attempting to connect to controller
					break;
				}
				break;
			case StateEvent.STATE_POWER_LOW:
				if (event.getAction() == StateEvent.ACTION_TRUE) {
					// controller has entered low power state
				} else {
					// controller has entered normal power state
				}
				break;
			}
		}
	}

	private Controller mController = null;

	public void onCreate(Context context) {
		mController = Controller.getInstance(context);
		
		mController.init();
		mController.setListener(this, new Handler());
	}

	public void onPause() {
		mController.onPause();
	}

	public void onResume() {
		mController.onResume();
	}

	public void onDestroy() {
		mController.exit();
	}
	
	private ControllerEventListener mControllerEventListener;
	@Override
	public void setControllerEventListener(ControllerEventListener listener) {
		mControllerEventListener = listener;
	}

	@Override
	public boolean dispatchKeyEvent(android.view.KeyEvent event) {
		return false;
	}

	@Override
	public boolean dispatchGenericMotionEvent(android.view.MotionEvent event) {
		return false;
	}

}
