package com.jme3.input.android;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import com.jme3.input.KeyInput;
import com.jme3.input.RawInputListener;
import com.jme3.input.TouchInput;
import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent;
import com.jme3.input.event.TouchEvent;
import com.jme3.input.event.TouchEvent.Type;
import com.jme3.math.Vector2f;
import com.jme3.util.RingBuffer;
import java.util.HashMap;
import java.util.logging.Logger;

/**
 * <code>AndroidInput</code> is one of the main components that connect jme with android. Is derived from GLSurfaceView and handles all Inputs
 * @author larynx
 *
 */
public class AndroidInput extends GLSurfaceView implements TouchInput,
        GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, ScaleGestureDetector.OnScaleGestureListener {

    final private static int MAX_EVENTS = 1024;
    // Custom settings
    public boolean mouseEventsEnabled = true;
    public boolean mouseEventsInvertX = false;
    public boolean mouseEventsInvertY = false;
    public boolean keyboardEventsEnabled = false;
    public boolean dontSendHistory = false;
    // Used to transfer events from android thread to GLThread
    final private RingBuffer<TouchEvent> eventQueue = new RingBuffer<TouchEvent>(MAX_EVENTS);
    final private RingBuffer<TouchEvent> eventPoolUnConsumed = new RingBuffer<TouchEvent>(MAX_EVENTS);
    final private RingBuffer<TouchEvent> eventPool = new RingBuffer<TouchEvent>(MAX_EVENTS);
    final private HashMap<Integer, Vector2f> lastPositions = new HashMap<Integer, Vector2f>();
    // Internal
    private ScaleGestureDetector scaledetector;
    private GestureDetector detector;
    private int lastX;
    private int lastY;
    private final static Logger logger = Logger.getLogger(AndroidInput.class.getName());
    private boolean isInitialized = false;
    private RawInputListener listener = null;
    private static final int[] ANDROID_TO_JME = {
        0x0, // unknown
        0x0, // key code soft left
        0x0, // key code soft right
        KeyInput.KEY_HOME,
        KeyInput.KEY_ESCAPE, // key back
        0x0, // key call
        0x0, // key endcall
        KeyInput.KEY_0,
        KeyInput.KEY_1,
        KeyInput.KEY_2,
        KeyInput.KEY_3,
        KeyInput.KEY_4,
        KeyInput.KEY_5,
        KeyInput.KEY_6,
        KeyInput.KEY_7,
        KeyInput.KEY_8,
        KeyInput.KEY_9,
        KeyInput.KEY_MULTIPLY,
        0x0, // key pound
        KeyInput.KEY_UP,
        KeyInput.KEY_DOWN,
        KeyInput.KEY_LEFT,
        KeyInput.KEY_RIGHT,
        KeyInput.KEY_RETURN, // dpad center
        0x0, // volume up
        0x0, // volume down
        KeyInput.KEY_POWER, // power (?)
        0x0, // camera
        0x0, // clear
        KeyInput.KEY_A,
        KeyInput.KEY_B,
        KeyInput.KEY_C,
        KeyInput.KEY_D,
        KeyInput.KEY_E,
        KeyInput.KEY_F,
        KeyInput.KEY_G,
        KeyInput.KEY_H,
        KeyInput.KEY_I,
        KeyInput.KEY_J,
        KeyInput.KEY_K,
        KeyInput.KEY_L,
        KeyInput.KEY_M,
        KeyInput.KEY_N,
        KeyInput.KEY_O,
        KeyInput.KEY_P,
        KeyInput.KEY_Q,
        KeyInput.KEY_R,
        KeyInput.KEY_S,
        KeyInput.KEY_T,
        KeyInput.KEY_U,
        KeyInput.KEY_V,
        KeyInput.KEY_W,
        KeyInput.KEY_X,
        KeyInput.KEY_Y,
        KeyInput.KEY_Z,
        KeyInput.KEY_COMMA,
        KeyInput.KEY_PERIOD,
        KeyInput.KEY_LMENU,
        KeyInput.KEY_RMENU,
        KeyInput.KEY_LSHIFT,
        KeyInput.KEY_RSHIFT,
        //        0x0, // fn
        //        0x0, // cap (?)

        KeyInput.KEY_TAB,
        KeyInput.KEY_SPACE,
        0x0, // sym (?) symbol
        0x0, // explorer
        0x0, // envelope
        KeyInput.KEY_RETURN, // newline/enter
        KeyInput.KEY_DELETE,
        KeyInput.KEY_GRAVE,
        KeyInput.KEY_MINUS,
        KeyInput.KEY_EQUALS,
        KeyInput.KEY_LBRACKET,
        KeyInput.KEY_RBRACKET,
        KeyInput.KEY_BACKSLASH,
        KeyInput.KEY_SEMICOLON,
        KeyInput.KEY_APOSTROPHE,
        KeyInput.KEY_SLASH,
        KeyInput.KEY_AT, // at (@)
        KeyInput.KEY_NUMLOCK, //0x0, // num
        0x0, //headset hook
        0x0, //focus
        KeyInput.KEY_ADD,
        KeyInput.KEY_LMETA, //menu
        0x0,//notification
        0x0,//search
        0x0,//media play/pause
        0x0,//media stop
        0x0,//media next
        0x0,//media previous
        0x0,//media rewind
        0x0,//media fastforward
        0x0,//mute
    };

    public AndroidInput(Context ctx, AttributeSet attribs) {
        super(ctx, attribs);
        detector = new GestureDetector(null, this, null, false);
        scaledetector = new ScaleGestureDetector(ctx, this);

    }

    public AndroidInput(Context ctx) {
        super(ctx);
        detector = new GestureDetector(null, this, null, false);
        scaledetector = new ScaleGestureDetector(ctx, this);
    }

    private TouchEvent getNextFreeTouchEvent() {
        return getNextFreeTouchEvent(false);
    }

    /**
     * Fetches a touch event from the reuse pool
     * @param wait if true waits for a reusable event to get available/released by an other thread, if false returns a new one if needed
     * @return a usable TouchEvent
     */
    private TouchEvent getNextFreeTouchEvent(boolean wait) {
        TouchEvent evt = null;
        synchronized (eventPoolUnConsumed) {
            int size = eventPoolUnConsumed.size();
            while (size > 0) {
                evt = eventPoolUnConsumed.pop();
                if (!evt.isConsumed()) {
                    eventPoolUnConsumed.push(evt);
                    evt = null;
                } else {
                    break;
                }
                size--;
            }
        }


        if (evt == null) {
            if (eventPool.isEmpty() && wait) {
                logger.warning("eventPool buffer underrun");
                boolean isEmpty;
                do {
                    synchronized (eventPool) {
                        isEmpty = eventPool.isEmpty();
                    }
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                    }
                } while (isEmpty);
                synchronized (eventPool) {
                    evt = eventPool.pop();
                }
            } else if (eventPool.isEmpty()) {
                evt = new TouchEvent();
                logger.warning("eventPool buffer underrun");
            } else {
                synchronized (eventPool) {
                    evt = eventPool.pop();
                }
            }
        }
        return evt;
    }

    /**
     * onTouchEvent gets called from android thread on touchpad events
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean bWasHandled = false;
        TouchEvent touch;
        //    System.out.println("native : " + event.getAction());
        int action = event.getAction() & MotionEvent.ACTION_MASK;
        int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
                >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        int pointerId = event.getPointerId(pointerIndex);

        // final int historySize = event.getHistorySize();
        //final int pointerCount = event.getPointerCount();


        switch (action) {

            case MotionEvent.ACTION_POINTER_DOWN:
            case MotionEvent.ACTION_DOWN:


                touch = getNextFreeTouchEvent();
                touch.set(Type.DOWN, event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex), 0, 0);
                touch.setPointerId(pointerId);
                touch.setTime(event.getEventTime());
                touch.setPressure(event.getPressure(pointerIndex));
                processEvent(touch);

                bWasHandled = true;
                break;

            case MotionEvent.ACTION_POINTER_UP:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:

                touch = getNextFreeTouchEvent();
                touch.set(Type.UP, event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex), 0, 0);
                touch.setPointerId(pointerId);
                touch.setTime(event.getEventTime());
                touch.setPressure(event.getPressure(pointerIndex));
                processEvent(touch);


                bWasHandled = true;
                break;
            case MotionEvent.ACTION_MOVE:


                // Convert all pointers into events
                for (int p = 0; p < event.getPointerCount(); p++) {
                    Vector2f lastPos = lastPositions.get(pointerIndex);
                    if (lastPos == null) {
                        lastPos = new Vector2f(event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex));
                        lastPositions.put(pointerId, lastPos);
                    }
                    touch = getNextFreeTouchEvent();
                    touch.set(Type.MOVE, event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex), event.getX(pointerIndex) - lastPos.x, this.getHeight() - event.getY(pointerIndex) - lastPos.y);
                    touch.setPointerId(pointerId);
                    touch.setTime(event.getEventTime());
                    touch.setPressure(event.getPressure(pointerIndex));
                    processEvent(touch);
                    lastPos.set(event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex));
                }
                bWasHandled = true;
                break;


            case MotionEvent.ACTION_OUTSIDE:
                break;

        }

        // Try to detect gestures        
        this.detector.onTouchEvent(event);
        this.scaledetector.onTouchEvent(event);

        return bWasHandled;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        TouchEvent evt;
        evt = getNextFreeTouchEvent();
        evt.set(TouchEvent.Type.KEY_DOWN);
        evt.setKeyCode(keyCode);
        evt.setCharacters(event.getCharacters());
        evt.setTime(event.getEventTime());

        // Send the event
        processEvent(evt);

        // Handle all keys ourself except Volume Up/Down
        if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
            return false;
        } else {
            return true;
        }

    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        TouchEvent evt;
        evt = getNextFreeTouchEvent();
        evt.set(TouchEvent.Type.KEY_UP);
        evt.setKeyCode(keyCode);
        evt.setCharacters(event.getCharacters());
        evt.setTime(event.getEventTime());

        // Send the event
        processEvent(evt);

        // Handle all keys ourself except Volume Up/Down
        if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
            return false;
        } else {
            return true;
        }
    }

    // -----------------------------------------
    // JME3 Input interface
    @Override
    public void initialize() {
        TouchEvent item;
        for (int i = 0; i < MAX_EVENTS; i++) {
            item = new TouchEvent();
            eventPool.push(item);
        }
        isInitialized = true;
    }

    @Override
    public void destroy() {
        isInitialized = false;

        // Clean up queues
        while (!eventPool.isEmpty()) {
            eventPool.pop();
        }
        while (!eventQueue.isEmpty()) {
            eventQueue.pop();
        }
    }

    @Override
    public boolean isInitialized() {
        return isInitialized;
    }

    @Override
    public void setInputListener(RawInputListener listener) {
        this.listener = listener;
    }

    @Override
    public long getInputTimeNanos() {
        return System.nanoTime();
    }
    // -----------------------------------------

    private void processEvent(TouchEvent event) {
        synchronized (eventQueue) {
            eventQueue.push(event);
        }
    }

    //  ---------------  INSIDE GLThread  --------------- 
    @Override
    public void update() {
        generateEvents();
    }

    private void generateEvents() {
        if (listener != null) {
            TouchEvent event;
            MouseButtonEvent btn;
            int newX;
            int newY;

            while (!eventQueue.isEmpty()) {
                synchronized (eventQueue) {
                    event = eventQueue.pop();
                }
                if (event != null) {
                    listener.onTouchEvent(event);

                    if (mouseEventsEnabled) {
                        if (mouseEventsInvertX) {
                            newX = this.getWidth() - (int) event.getX();
                        } else {
                            newX = (int) event.getX();
                        }

                        if (mouseEventsInvertY) {
                            newY = this.getHeight() - (int) event.getY();
                        } else {
                            newY = (int) event.getY();
                        }

                        switch (event.getType()) {
                            case DOWN:
                                // Handle mouse down event 
                                btn = new MouseButtonEvent(0, true, newX, newY);
                                btn.setTime(event.getTime());
                                listener.onMouseButtonEvent(btn);
                                // Store current pos
                                lastX = -1;
                                lastY = -1;
                                break;

                            case UP:
                                // Handle mouse up event 
                                btn = new MouseButtonEvent(0, false, newX, newY);
                                btn.setTime(event.getTime());
                                listener.onMouseButtonEvent(btn);
                                // Store current pos
                                lastX = -1;
                                lastY = -1;
                                break;

                            case MOVE:
                                int dx;
                                int dy;
                                if (lastX != -1) {
                                    dx = newX - lastX;
                                    dy = newY - lastY;
                                } else {
                                    dx = 0;
                                    dy = 0;
                                }
                                MouseMotionEvent mot = new MouseMotionEvent(newX, newY, dx, dy, 0, 0);
                                mot.setTime(event.getTime());
                                listener.onMouseMotionEvent(mot);
                                lastX = newX;
                                lastY = newY;
                                break;
                        }


                    }
                }

                if (event.isConsumed() == false) {
                    synchronized (eventPoolUnConsumed) {
                        eventPoolUnConsumed.push(event);
                    }

                } else {
                    synchronized (eventPool) {
                        eventPool.push(event);
                    }
                }
            }

        }
    }
    //  --------------- ENDOF INSIDE GLThread  --------------- 

    // --------------- Gesture detected callback events  --------------- 
    public boolean onDown(MotionEvent event) {
        return false;
    }

    public void onLongPress(MotionEvent event) {
        TouchEvent touch = getNextFreeTouchEvent();
        touch.set(Type.LONGPRESSED, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
        touch.setPointerId(0);
        touch.setTime(event.getEventTime());
        processEvent(touch);
    }

    public boolean onFling(MotionEvent event, MotionEvent event2, float vx, float vy) {
        TouchEvent touch = getNextFreeTouchEvent();
        touch.set(Type.FLING, event.getX(), this.getHeight() - event.getY(), vx, vy);
        touch.setPointerId(0);
        touch.setTime(event.getEventTime());
        processEvent(touch);

        return true;
    }

    public boolean onSingleTapConfirmed(MotionEvent event) {
        //Nothing to do here the tap has already been detected.
        return false;
    }

    public boolean onDoubleTap(MotionEvent event) {
        TouchEvent touch = getNextFreeTouchEvent();
        touch.set(Type.DOUBLETAP, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
        touch.setPointerId(0);
        touch.setTime(event.getEventTime());
        processEvent(touch);
        return true;
    }

    public boolean onDoubleTapEvent(MotionEvent event) {
        return false;
    }

    public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
        TouchEvent touch = getNextFreeTouchEvent();
        touch.set(Type.SCALE_START, scaleGestureDetector.getFocusX(), scaleGestureDetector.getFocusY(), 0f, 0f);
        touch.setPointerId(0);
        touch.setTime(scaleGestureDetector.getEventTime());
        touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
        touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
        processEvent(touch);
        //    System.out.println("scaleBegin");

        return true;
    }

    public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
        TouchEvent touch = getNextFreeTouchEvent();
        touch.set(Type.SCALE_MOVE, scaleGestureDetector.getFocusX(), this.getHeight() - scaleGestureDetector.getFocusY(), 0f, 0f);
        touch.setPointerId(0);
        touch.setTime(scaleGestureDetector.getEventTime());
        touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
        touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
        processEvent(touch);
        //   System.out.println("scale");

        return false;
    }

    public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
        TouchEvent touch = getNextFreeTouchEvent();
        touch.set(Type.SCALE_END, scaleGestureDetector.getFocusX(), this.getHeight() - scaleGestureDetector.getFocusY(), 0f, 0f);
        touch.setPointerId(0);
        touch.setTime(scaleGestureDetector.getEventTime());
        touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
        touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
        processEvent(touch);
    }

    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        TouchEvent touch = getNextFreeTouchEvent();
        touch.set(Type.SCROLL, e1.getX(), this.getHeight() - e1.getY(), distanceX, distanceY * (-1));
        touch.setPointerId(0);
        touch.setTime(e1.getEventTime());
        processEvent(touch);
        //System.out.println("scroll " + e1.getPointerCount());
        return false;
    }

    public void onShowPress(MotionEvent event) {
        TouchEvent touch = getNextFreeTouchEvent();
        touch.set(Type.SHOWPRESS, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
        touch.setPointerId(0);
        touch.setTime(event.getEventTime());
        processEvent(touch);
    }

    public boolean onSingleTapUp(MotionEvent event) {
        TouchEvent touch = getNextFreeTouchEvent();
        touch.set(Type.TAP, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
        touch.setPointerId(0);
        touch.setTime(event.getEventTime());
        processEvent(touch);
        return true;
    }

    @Override
    public void setSimulateMouse(boolean simulate) {
        mouseEventsEnabled = simulate;
    }

    @Override
    public void setSimulateKeyboard(boolean simulate) {
        keyboardEventsEnabled = simulate;
    }

    @Override
    public void setOmitHistoricEvents(boolean dontSendHistory) {
        this.dontSendHistory = dontSendHistory;
    }

    // TODO: move to TouchInput
    public boolean isMouseEventsEnabled() {
        return mouseEventsEnabled;
    }

    public void setMouseEventsEnabled(boolean mouseEventsEnabled) {
        this.mouseEventsEnabled = mouseEventsEnabled;
    }

    public boolean isMouseEventsInvertY() {
        return mouseEventsInvertY;
    }

    public void setMouseEventsInvertY(boolean mouseEventsInvertY) {
        this.mouseEventsInvertY = mouseEventsInvertY;
    }

    public boolean isMouseEventsInvertX() {
        return mouseEventsInvertX;
    }

    public void setMouseEventsInvertX(boolean mouseEventsInvertX) {
        this.mouseEventsInvertX = mouseEventsInvertX;
    }
}
