package org.cocos2dx.lib;


import org.cocos2dx.lib.GameControllerDelegate;

import tv.ouya.console.api.OuyaController;
import android.content.Context;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.KeyEvent;
import android.view.MotionEvent;

public class GameControllerOuya implements GameControllerDelegate{
    
    private SparseIntArray mKeyMap;
    
    private SparseArray<String> mGameController = new SparseArray<String>();
    
    public GameControllerOuya(){
        mKeyMap = new SparseIntArray(20);
        mKeyMap.put(OuyaController.BUTTON_A, GameControllerDelegate.BUTTON_B);
        mKeyMap.put(OuyaController.BUTTON_O, GameControllerDelegate.BUTTON_A);
        mKeyMap.put(OuyaController.BUTTON_U, GameControllerDelegate.BUTTON_X);
        mKeyMap.put(OuyaController.BUTTON_Y, GameControllerDelegate.BUTTON_Y);
        mKeyMap.put(OuyaController.BUTTON_DPAD_DOWN, GameControllerDelegate.BUTTON_DPAD_DOWN);
        mKeyMap.put(OuyaController.BUTTON_DPAD_LEFT, GameControllerDelegate.BUTTON_DPAD_LEFT);
        mKeyMap.put(OuyaController.BUTTON_DPAD_RIGHT, GameControllerDelegate.BUTTON_DPAD_RIGHT);
        mKeyMap.put(OuyaController.BUTTON_DPAD_UP, GameControllerDelegate.BUTTON_DPAD_UP);
        mKeyMap.put(OuyaController.BUTTON_L1, GameControllerDelegate.BUTTON_LEFT_SHOULDER);
        mKeyMap.put(OuyaController.BUTTON_R1,  GameControllerDelegate.BUTTON_RIGHT_SHOULDER);
        
        mKeyMap.put(OuyaController.BUTTON_L3, GameControllerDelegate.BUTTON_LEFT_THUMBSTICK);
        mKeyMap.put(OuyaController.BUTTON_R3, GameControllerDelegate.BUTTON_RIGHT_THUMBSTICK);
    }
    
    public void onCreate(Context context) {
        OuyaController.init(context);
    }
    
    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;
    
    public boolean dispatchGenericMotionEvent(MotionEvent event) {
        boolean handled = OuyaController.onGenericMotionEvent(event);
        
        if (handled && mControllerEventListener != null)
        {
            int deviceId = event.getDeviceId();
            String deviceName = event.getDevice().getName();
            OuyaController c = OuyaController.getControllerByDeviceId(deviceId);
            if (mGameController.get(deviceId) == null) {
                GameControllerHelper.gatherControllers(mGameController);
                mGameController.append(deviceId, deviceName);
            }
            
            float newLeftTrigger = c.getAxisValue(OuyaController.AXIS_L2);
            if (Float.compare(newLeftTrigger, mOldLeftTrigger) != 0) {
                mControllerEventListener.onAxisEvent(deviceName, deviceId, GameControllerDelegate.BUTTON_LEFT_TRIGGER, newLeftTrigger, true);
                mOldLeftTrigger = newLeftTrigger;
            }
            
            float newRightTrigger = c.getAxisValue(OuyaController.AXIS_R2);
            if (Float.compare(newRightTrigger, mOldRightTrigger) != 0) {
                mControllerEventListener.onAxisEvent(deviceName, deviceId, GameControllerDelegate.BUTTON_RIGHT_TRIGGER, newRightTrigger, true);
                mOldRightTrigger = newRightTrigger;
            }
            
            float newLeftThumbstickX = c.getAxisValue(OuyaController.AXIS_LS_X);
            if (Float.compare(newLeftThumbstickX, mOldLeftThumbstickX) != 0) {
                if (Float.compare(newLeftThumbstickX, 0.0f) == 0) {
                    mControllerEventListener.onAxisEvent(deviceName, deviceId, GameControllerDelegate.THUMBSTICK_LEFT_X, 0.0f, true);
                }else {
                    mControllerEventListener.onAxisEvent(deviceName, deviceId, GameControllerDelegate.THUMBSTICK_LEFT_X, newLeftThumbstickX, true);
                }
                mOldLeftThumbstickX = newLeftThumbstickX;
            }
            
            float newLeftThumbstickY = c.getAxisValue(OuyaController.AXIS_LS_Y);
            if (Float.compare(newLeftThumbstickY, mOldLeftThumbstickY) != 0) {
                if (Float.compare(newLeftThumbstickY, 0.0f) == 0) {
                    mControllerEventListener.onAxisEvent(deviceName, deviceId, GameControllerDelegate.THUMBSTICK_LEFT_Y, 0.0f, true);
                }else {
                    mControllerEventListener.onAxisEvent(deviceName, deviceId, GameControllerDelegate.THUMBSTICK_LEFT_Y, newLeftThumbstickY, true);
                }
                mOldLeftThumbstickY = newLeftThumbstickY;
            }
            
            float newRightThumbstickX = c.getAxisValue(OuyaController.AXIS_RS_X);
            if (Float.compare(newRightThumbstickX, mOldRightThumbstickX) != 0) {
                if (Float.compare(newRightThumbstickX, 0.0f) == 0) {
                    mControllerEventListener.onAxisEvent(deviceName, deviceId, GameControllerDelegate.THUMBSTICK_RIGHT_X, 0.0f, true);
                }else {
                    mControllerEventListener.onAxisEvent(deviceName, deviceId, GameControllerDelegate.THUMBSTICK_RIGHT_X, newRightThumbstickX, true);
                }
                mOldRightThumbstickX = newRightThumbstickX;
            }
            
            float newRightThumbstickY = c.getAxisValue(OuyaController.AXIS_RS_Y);
            if (Float.compare(newRightThumbstickY, mOldRightThumbstickY) != 0) {
                if (Float.compare(newRightThumbstickY, 0.0f) == 0) {
                    mControllerEventListener.onAxisEvent(deviceName, deviceId, GameControllerDelegate.THUMBSTICK_RIGHT_Y, 0.0f, true);
                }else {
                    mControllerEventListener.onAxisEvent(deviceName, deviceId, GameControllerDelegate.THUMBSTICK_RIGHT_Y, newRightThumbstickY, true);
                }
                mOldRightThumbstickY = newRightThumbstickY;
            }
        }
        
        return handled;
    }
    
    public boolean dispatchKeyEvent(KeyEvent event) {
        boolean handled = false;
        
        int action = event.getAction();
        int keyCode = event.getKeyCode();
        
        if (action == KeyEvent.ACTION_DOWN) {
            handled = OuyaController.onKeyDown(keyCode, event);
        }
        else if (action == KeyEvent.ACTION_UP) {
            handled = OuyaController.onKeyUp(keyCode, event);
        }
        
        if (handled && mControllerEventListener != null) {
            boolean isAnalog = false;
            
            if (keyCode == KeyEvent.KEYCODE_BUTTON_THUMBL || keyCode == KeyEvent.KEYCODE_BUTTON_THUMBR){
                isAnalog = true;
            }
            
            int deviceId = event.getDeviceId();
            String deviceName = event.getDevice().getName();
            
            if (mGameController.get(deviceId) == null) {
                GameControllerHelper.gatherControllers(mGameController);
                mGameController.append(deviceId, deviceName);
            }
            if (action == KeyEvent.ACTION_DOWN) {
                mControllerEventListener.onButtonEvent(deviceName, deviceId, mKeyMap.get(keyCode), true, 1.0f, isAnalog);
            }else {
                mControllerEventListener.onButtonEvent(deviceName, deviceId, mKeyMap.get(keyCode), false, 0.0f, isAnalog);
            }
        }
        
        return handled;
    }
    
    public void onPause() {
        // show the mouse cursor
        OuyaController.showCursor(true);
    }
    
    public void onResume() {
        // hide the mouse cursor
        OuyaController.showCursor(false);
    }
    
    public void onDestroy() {
        
    }

    private ControllerEventListener mControllerEventListener;
    
    @Override
    public void setControllerEventListener(ControllerEventListener listener) {
        mControllerEventListener = listener;
    }
    
}
