package com.xugame.app;

import android.view.InputDevice;
import android.view.MotionEvent;

import com.xugame.gameconsole.util.DebugUtil;

import java.util.ArrayList;
import java.util.HashSet;

public class JoypadManager {
    protected static JoypadHandler mJoystickHandler = null;
    public static void initialize() {
        if (mJoystickHandler == null) {
            mJoystickHandler = new JoypadHandler_API();
        }
    }

    public static void uninitialize() {
        mJoystickHandler.removeInputDevices();
        mJoystickHandler = null;
    }

    // Using for JNI
    public static void pollInputDevices() {
        mJoystickHandler.pollInputDevices();
    }

    // Check if a given device is considered a possible SDL joystick
    public static boolean isDeviceJoystick(int deviceId) {
        InputDevice device = InputDevice.getDevice(deviceId);
        // We cannot use InputDevice.isVirtual before API 16, so let's accept
        // only nonnegative device ids (VIRTUAL_KEYBOARD equals -1)
        if ((device == null) || (deviceId < 0)) {
            return false;
        }
        if(device.getName().equals("sunxi-gpadc"))
            return true;
        if(device.getName().equals("robot"))
            return true;

        if (device.isVirtual()) {
            return false;
        }

        int sources = device.getSources();

        /* This is called for every button press, so let's not spam the logs */
        /*
        if ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
            Log.v(TAG, "Input device " + device.getName() + " has class joystick.");
        }
        if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) {
            Log.v(TAG, "Input device " + device.getName() + " is a dpad.");
        }
        if ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) {
            Log.v(TAG, "Input device " + device.getName() + " is a gamepad.");
        }
        */
        InputDevice.MotionRange range = device.getMotionRange(MotionEvent.AXIS_HAT_X);
        if(range == null)
            return false;

        range = device.getMotionRange(MotionEvent.AXIS_HAT_Y);
        if(range == null)
            return false;

        return ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0 ||
                ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) ||
                ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
        );
    }

    public static native void addJoystickNative(int deviceId, int deviceSource);
    public static native void removeJoystickNative(int deviceId);
}

class JoypadHandler {
    /**
     * Handles adding and removing of input devices.
     */
    public void pollInputDevices() {
    }

    public void removeInputDevices() {
    }
}

class JoypadHandler_API extends JoypadHandler {
    private final HashSet<Integer> mJoypadIds;

    public JoypadHandler_API() {
        mJoypadIds = new HashSet<Integer>();
    }

    @Override
    public void pollInputDevices() {
        int[] deviceIds = InputDevice.getDeviceIds();

        for (int deviceId : deviceIds) {
//            DebugUtil.i("JOYPAD:",""+InputDevice.getDevice(deviceId).toString());
            if (!mJoypadIds.contains(deviceId)) {
                if (JoypadManager.isDeviceJoystick(deviceId)) {
//                    DebugUtil.i("JOYPAD has:",""+InputDevice.getDevice(deviceId).toString());

                    InputDevice joypadDevice = InputDevice.getDevice(deviceId);
                    mJoypadIds.add(deviceId);
                    JoypadManager.addJoystickNative(
                            deviceId,
                            joypadDevice.getSources()
                    );
                }
            }
        }

        ArrayList<Integer> removedDevices = null;
        for (Integer joystickId : mJoypadIds) {
            int i;
            for (i = 0; i < deviceIds.length; i++) {
                if (joystickId == deviceIds[i])
                    break;
            }

            if (i == deviceIds.length) {
                if (removedDevices == null) {
                    removedDevices = new ArrayList<Integer>();
                }
                removedDevices.add(joystickId);
            }
        }

        if (removedDevices != null) {
            for (int deviceId : removedDevices) {
                JoypadManager.removeJoystickNative(deviceId);
                mJoypadIds.remove(deviceId);
            }
        }
    }

    @Override
    public void removeInputDevices() {
        for (int deviceId : mJoypadIds) {
            JoypadManager.removeJoystickNative(deviceId);
        }
        mJoypadIds.clear();
    }
}
