/*
 * Copyright (c) 2009-2012 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.jme3.input;

import com.jme3.app.Application;
import com.jme3.input.controls.*;
import com.jme3.input.event.*;
import com.jme3.math.FastMath;
import com.jme3.math.Vector2f;
import com.jme3.util.IntMap;
import com.jme3.util.IntMap.Entry;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * The <code>InputManager</code> is responsible for converting input events
 * received from the Key, Mouse and Joy Input implementations into an
 * abstract, input device independent representation that user code can use.
 * <p>
 * By default an <code>InputManager</code> is included with every Application instance for use
 * in user code to query input, unless the Application is created as headless
 * or with input explicitly disabled.
 * <p>
 * The input manager has two concepts, a {@link Trigger} and a mapping.
 * A trigger represents a specific input trigger, such as a key button, 
 * or a mouse axis. A mapping represents a link onto one or several triggers, 
 * when the appropriate trigger is activated (e.g. a key is pressed), the 
 * mapping will be invoked. Any listeners registered to receive an event
 * from the mapping will have an event raised.
 * <p>
 * There are two types of events that {@link InputListener input listeners}
 * can receive, one is {@link ActionListener#onAction(java.lang.String, boolean, float) action}
 * events and another is {@link AnalogListener#onAnalog(java.lang.String, float, float) analog}
 * events. 
 * <p>
 * <code>onAction</code> events are raised when the specific input
 * activates or deactivates. For a digital input such as key press, the <code>onAction()</code>
 * event will be raised with the <code>isPressed</code> argument equal to true,
 * when the key is released, <code>onAction</code> is called again but this time
 * with the <code>isPressed</code> argument set to false.
 * For analog inputs, the <code>onAction</code> method will be called any time
 * the input is non-zero, however an exception to this is for joystick axis inputs,
 * which are only called when the input is above the {@link InputManager#setAxisDeadZone(float) dead zone}.
 * <p>
 * <code>onAnalog</code> events are raised every frame while the input is activated.
 * For digital inputs, every frame that the input is active will cause the
 * <code>onAnalog</code> method to be called, the argument <code>value</code>
 * argument will equal to the frame's time per frame (TPF) value but only
 * for digital inputs. For analog inputs however, the <code>value</code> argument
 * will equal the actual analog value.
 */
public class InputManager implements RawInputListener {

    private static final Logger logger = Logger.getLogger(InputManager.class.getName());
    private final KeyInput keys;
    private final MouseInput mouse;
    private final JoyInput joystick;
    private final TouchInput touch;
    private float frameTPF;
    private long lastLastUpdateTime = 0;
    private long lastUpdateTime = 0;
    private long frameDelta = 0;
    private long firstTime = 0;
    private boolean eventsPermitted = false;
    private boolean mouseVisible = true;
    private boolean safeMode = false;
    private float axisDeadZone = 0.05f;
    private Vector2f cursorPos = new Vector2f();
    private Joystick[] joysticks;
    private final IntMap<ArrayList<Mapping>> bindings = new IntMap<ArrayList<Mapping>>();
    private final HashMap<String, Mapping> mappings = new HashMap<String, Mapping>();
    private final IntMap<Long> pressedButtons = new IntMap<Long>();
    private final IntMap<Float> axisValues = new IntMap<Float>();
    private ArrayList<RawInputListener> rawListeners = new ArrayList<RawInputListener>();
    private RawInputListener[] rawListenerArray = null;
    private ArrayList<InputEvent> inputQueue = new ArrayList<InputEvent>();

    private static class Mapping {

        private final String name;
        private final ArrayList<Integer> triggers = new ArrayList<Integer>();
        private final ArrayList<InputListener> listeners = new ArrayList<InputListener>();

        public Mapping(String name) {
            this.name = name;
        }
    }

    /**
     * Initializes the InputManager.
     * 
     * <p>This should only be called internally in {@link Application}.
     *
     * @param mouse
     * @param keys
     * @param joystick
     * @param touch
     * @throws IllegalArgumentException If either mouseInput or keyInput are null.
     */
    public InputManager(MouseInput mouse, KeyInput keys, JoyInput joystick, TouchInput touch) {
        if (keys == null || mouse == null) {
            throw new NullPointerException("Mouse or keyboard cannot be null");
        }

        this.keys = keys;
        this.mouse = mouse;
        this.joystick = joystick;
        this.touch = touch;

        keys.setInputListener(this);
        mouse.setInputListener(this);
        if (joystick != null) {
            joystick.setInputListener(this);
            joysticks = joystick.loadJoysticks(this);
        }
        if (touch != null) {
            touch.setInputListener(this);
        }

        firstTime = keys.getInputTimeNanos();
    }

    private void invokeActions(int hash, boolean pressed) {
        ArrayList<Mapping> maps = bindings.get(hash);
        if (maps == null) {
            return;
        }

        int size = maps.size();
        for (int i = size - 1; i >= 0; i--) {
            Mapping mapping = maps.get(i);
            ArrayList<InputListener> listeners = mapping.listeners;
            int listenerSize = listeners.size();
            for (int j = listenerSize - 1; j >= 0; j--) {
                InputListener listener = listeners.get(j);
                if (listener instanceof ActionListener) {
                    ((ActionListener) listener).onAction(mapping.name, pressed, frameTPF);
                }
            }
        }
    }

    private float computeAnalogValue(long timeDelta) {
        if (safeMode || frameDelta == 0) {
            return 1f;
        } else {
            return FastMath.clamp((float) timeDelta / (float) frameDelta, 0, 1);
        }
    }

    private void invokeTimedActions(int hash, long time, boolean pressed) {
        if (!bindings.containsKey(hash)) {
            return;
        }

        if (pressed) {
            pressedButtons.put(hash, time);
        } else {
            Long pressTimeObj = pressedButtons.remove(hash);
            if (pressTimeObj == null) {
                return; // under certain circumstances it can be null, ignore
            }                        // the event then.

            long pressTime = pressTimeObj;
            long lastUpdate = lastLastUpdateTime;
            long releaseTime = time;
            long timeDelta = releaseTime - Math.max(pressTime, lastUpdate);

            if (timeDelta > 0) {
                invokeAnalogs(hash, computeAnalogValue(timeDelta), false);
            }
        }
    }

    private void invokeUpdateActions() {
      if (pressedButtons.size() > 0) for (Entry<Long> pressedButton : pressedButtons) {
            int hash = pressedButton.getKey();

            long pressTime = pressedButton.getValue();
            long timeDelta = lastUpdateTime - Math.max(lastLastUpdateTime, pressTime);

            if (timeDelta > 0) {
                invokeAnalogs(hash, computeAnalogValue(timeDelta), false);
            }
        }

      if (axisValues.size() > 0) for (Entry<Float> axisValue : axisValues) {
            int hash = axisValue.getKey();
            float value = axisValue.getValue();
            invokeAnalogs(hash, value * frameTPF, true);
        }
    }

    private void invokeAnalogs(int hash, float value, boolean isAxis) {
        ArrayList<Mapping> maps = bindings.get(hash);
        if (maps == null) {
            return;
        }

        if (!isAxis) {
            value *= frameTPF;
        }

        int size = maps.size();
        for (int i = size - 1; i >= 0; i--) {
            Mapping mapping = maps.get(i);
            ArrayList<InputListener> listeners = mapping.listeners;
            int listenerSize = listeners.size();
            for (int j = listenerSize - 1; j >= 0; j--) {
                InputListener listener = listeners.get(j);
                if (listener instanceof AnalogListener) {
                    // NOTE: multiply by TPF for any button bindings
                    ((AnalogListener) listener).onAnalog(mapping.name, value, frameTPF);
                }
            }
        }
    }

    private void invokeAnalogsAndActions(int hash, float value, boolean applyTpf) {
        if (value < axisDeadZone) {
            invokeAnalogs(hash, value, !applyTpf);
            return;
        }

        ArrayList<Mapping> maps = bindings.get(hash);
        if (maps == null) {
            return;
        }

        boolean valueChanged = !axisValues.containsKey(hash);
        if (applyTpf) {
            value *= frameTPF;
        }

        int size = maps.size();
        for (int i = size - 1; i >= 0; i--) {
            Mapping mapping = maps.get(i);
            ArrayList<InputListener> listeners = mapping.listeners;
            int listenerSize = listeners.size();
            for (int j = listenerSize - 1; j >= 0; j--) {
                InputListener listener = listeners.get(j);

                if (listener instanceof ActionListener && valueChanged) {
                    ((ActionListener) listener).onAction(mapping.name, true, frameTPF);
                }

                if (listener instanceof AnalogListener) {
                    ((AnalogListener) listener).onAnalog(mapping.name, value, frameTPF);
                }

            }
        }
    }

    /**
     * Callback from RawInputListener. Do not use.
     */
    public void beginInput() {
    }

    /**
     * Callback from RawInputListener. Do not use.
     */
    public void endInput() {
    }

    private void onJoyAxisEventQueued(JoyAxisEvent evt) {
//        for (int i = 0; i < rawListeners.size(); i++){
//            rawListeners.get(i).onJoyAxisEvent(evt);
//        }

        int joyId = evt.getJoyIndex();
        int axis = evt.getAxisIndex();
        float value = evt.getValue();
        if (value < axisDeadZone && value > -axisDeadZone) {
            int hash1 = JoyAxisTrigger.joyAxisHash(joyId, axis, true);
            int hash2 = JoyAxisTrigger.joyAxisHash(joyId, axis, false);

            Float val1 = axisValues.get(hash1);
            Float val2 = axisValues.get(hash2);

            if (val1 != null && val1.floatValue() > axisDeadZone) {
                invokeActions(hash1, false);
            }
            if (val2 != null && val2.floatValue() > axisDeadZone) {
                invokeActions(hash2, false);
            }

            axisValues.remove(hash1);
            axisValues.remove(hash2);

        } else if (value < 0) {
            int hash = JoyAxisTrigger.joyAxisHash(joyId, axis, true);
            int otherHash = JoyAxisTrigger.joyAxisHash(joyId, axis, false);
            invokeAnalogsAndActions(hash, -value, true);
            axisValues.put(hash, -value);
            axisValues.remove(otherHash);
        } else {
            int hash = JoyAxisTrigger.joyAxisHash(joyId, axis, false);
            int otherHash = JoyAxisTrigger.joyAxisHash(joyId, axis, true);
            invokeAnalogsAndActions(hash, value, true);
            axisValues.put(hash, value);
            axisValues.remove(otherHash);
        }
    }

    /**
     * Callback from RawInputListener. Do not use.
     */
    public void onJoyAxisEvent(JoyAxisEvent evt) {
        if (!eventsPermitted) {
            throw new UnsupportedOperationException("JoyInput has raised an event at an illegal time.");
        }

        inputQueue.add(evt);
    }

    private void onJoyButtonEventQueued(JoyButtonEvent evt) {
//        for (int i = 0; i < rawListeners.size(); i++){
//            rawListeners.get(i).onJoyButtonEvent(evt);
//        }

        int hash = JoyButtonTrigger.joyButtonHash(evt.getJoyIndex(), evt.getButtonIndex());
        invokeActions(hash, evt.isPressed());
        invokeTimedActions(hash, evt.getTime(), evt.isPressed());
    }

    /**
     * Callback from RawInputListener. Do not use.
     */
    public void onJoyButtonEvent(JoyButtonEvent evt) {
        if (!eventsPermitted) {
            throw new UnsupportedOperationException("JoyInput has raised an event at an illegal time.");
        }

        inputQueue.add(evt);
    }

    private void onMouseMotionEventQueued(MouseMotionEvent evt) {
//        for (int i = 0; i < rawListeners.size(); i++){
//            rawListeners.get(i).onMouseMotionEvent(evt);
//        }

        if (evt.getDX() != 0) {
            float val = Math.abs(evt.getDX()) / 1024f;
            invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_X, evt.getDX() < 0), val, false);
        }
        if (evt.getDY() != 0) {
            float val = Math.abs(evt.getDY()) / 1024f;
            invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_Y, evt.getDY() < 0), val, false);
        }
        if (evt.getDeltaWheel() != 0) {
            float val = Math.abs(evt.getDeltaWheel()) / 100f;
            invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_WHEEL, evt.getDeltaWheel() < 0), val, false);
        }
    }

    /**
     * Callback from RawInputListener. Do not use.
     */
    public void onMouseMotionEvent(MouseMotionEvent evt) {
        if (!eventsPermitted) {
            throw new UnsupportedOperationException("MouseInput has raised an event at an illegal time.");
        }

        cursorPos.set(evt.getX(), evt.getY());
        inputQueue.add(evt);
    }

    private void onMouseButtonEventQueued(MouseButtonEvent evt) {
        int hash = MouseButtonTrigger.mouseButtonHash(evt.getButtonIndex());
        invokeActions(hash, evt.isPressed());
        invokeTimedActions(hash, evt.getTime(), evt.isPressed());
    }

    /**
     * Callback from RawInputListener. Do not use.
     */
    public void onMouseButtonEvent(MouseButtonEvent evt) {
        if (!eventsPermitted) {
            throw new UnsupportedOperationException("MouseInput has raised an event at an illegal time.");
        }
        //updating cursor pos on click, so that non android touch events can properly update cursor position.
        cursorPos.set(evt.getX(), evt.getY());
        inputQueue.add(evt);
    }

    private void onKeyEventQueued(KeyInputEvent evt) {
        if (evt.isRepeating()) {
            return; // repeat events not used for bindings
        }
        
        int hash = KeyTrigger.keyHash(evt.getKeyCode());
        invokeActions(hash, evt.isPressed());
        invokeTimedActions(hash, evt.getTime(), evt.isPressed());
    }

    /**
     * Callback from RawInputListener. Do not use.
     */
    public void onKeyEvent(KeyInputEvent evt) {
        if (!eventsPermitted) {
            throw new UnsupportedOperationException("KeyInput has raised an event at an illegal time.");
        }

        inputQueue.add(evt);
    }

    /**
     * Set the deadzone for joystick axes.
     * 
     * <p>{@link ActionListener#onAction(java.lang.String, boolean, float) }
     * events will only be raised if the joystick axis value is greater than
     * the <code>deadZone</code>.
     * 
     * @param deadZone the deadzone for joystick axes. 
     */
    public void setAxisDeadZone(float deadZone) {
        this.axisDeadZone = deadZone;
    }

    /**
     * Returns the deadzone for joystick axes.
     * 
     * @return the deadzone for joystick axes.
     */
    public float getAxisDeadZone() {
        return axisDeadZone;
    }
    
    /**
     * Adds a new listener to receive events on the given mappings.
     * 
     * <p>The given InputListener will be registered to receive events
     * on the specified mapping names. When a mapping raises an event, the
     * listener will have its appropriate method invoked, either
     * {@link ActionListener#onAction(java.lang.String, boolean, float) }
     * or {@link AnalogListener#onAnalog(java.lang.String, float, float) }
     * depending on which interface the <code>listener</code> implements. 
     * If the listener implements both interfaces, then it will receive the
     * appropriate event for each method.
     * 
     * @param listener The listener to register to receive input events.
     * @param mappingNames The mapping names which the listener will receive
     * events from.
     * 
     * @see InputManager#removeListener(com.jme3.input.controls.InputListener) 
     */
    public void addListener(InputListener listener, String... mappingNames) {
        for (String mappingName : mappingNames) {
            Mapping mapping = mappings.get(mappingName);
            if (mapping == null) {
                mapping = new Mapping(mappingName);
                mappings.put(mappingName, mapping);
            }
            if (!mapping.listeners.contains(listener)) {
                mapping.listeners.add(listener);
            }
        }
    }

    /**
     * Removes a listener from receiving events.
     * 
     * <p>This will unregister the listener from any mappings that it
     * was previously registered with via 
     * {@link InputManager#addListener(com.jme3.input.controls.InputListener, java.lang.String[]) }.
     * 
     * @param listener The listener to unregister.
     * 
     * @see InputManager#addListener(com.jme3.input.controls.InputListener, java.lang.String[]) 
     */
    public void removeListener(InputListener listener) {
        for (Mapping mapping : mappings.values()) {
            mapping.listeners.remove(listener);
        }
    }

    /**
     * Create a new mapping to the given triggers.
     * 
     * <p>
     * The given mapping will be assigned to the given triggers, when
     * any of the triggers given raise an event, the listeners
     * registered to the mappings will receive appropriate events.
     * 
     * @param mappingName The mapping name to assign.
     * @param triggers The triggers to which the mapping is to be registered.
     * 
     * @see InputManager#deleteMapping(java.lang.String) 
     */
    public void addMapping(String mappingName, Trigger... triggers) {
        Mapping mapping = mappings.get(mappingName);
        if (mapping == null) {
            mapping = new Mapping(mappingName);
            mappings.put(mappingName, mapping);
        }

        for (Trigger trigger : triggers) {
            int hash = trigger.triggerHashCode();
            ArrayList<Mapping> names = bindings.get(hash);
            if (names == null) {
                names = new ArrayList<Mapping>();
                bindings.put(hash, names);
            }
            if (!names.contains(mapping)) {
                names.add(mapping);
                mapping.triggers.add(hash);
            } else {
                logger.log(Level.WARNING, "Attempted to add mapping \"{0}\" twice to trigger.", mappingName);
            }
        }
    }

    /**
     * Returns true if this InputManager has a mapping registered
     * for the given mappingName.
     *
     * @param mappingName The mapping name to check.
     *
     * @see InputManager#addMapping(java.lang.String, com.jme3.input.controls.Trigger[]) 
     * @see InputManager#deleteMapping(java.lang.String) 
     */ 
    public boolean hasMapping(String mappingName) {
        return mappings.containsKey(mappingName);
    }
    
    /**
     * Deletes a mapping from receiving trigger events.
     * 
     * <p>
     * The given mapping will no longer be assigned to receive trigger
     * events.
     * 
     * @param mappingName The mapping name to unregister.
     * 
     * @see InputManager#addMapping(java.lang.String, com.jme3.input.controls.Trigger[]) 
     */
    public void deleteMapping(String mappingName) {
        Mapping mapping = mappings.remove(mappingName);
        if (mapping == null) {
            throw new IllegalArgumentException("Cannot find mapping: " + mappingName);
        }

        ArrayList<Integer> triggers = mapping.triggers;
        for (int i = triggers.size() - 1; i >= 0; i--) {
            int hash = triggers.get(i);
            ArrayList<Mapping> maps = bindings.get(hash);
            maps.remove(mapping);
        }
    }

    /**
     * Deletes a specific trigger registered to a mapping.
     * 
     * <p>
     * The given mapping will no longer receive events raised by the 
     * trigger.
     * 
     * @param mappingName The mapping name to cease receiving events from the 
     * trigger.
     * @param trigger The trigger to no longer invoke events on the mapping.
     */
    public void deleteTrigger(String mappingName, Trigger trigger) {
        Mapping mapping = mappings.get(mappingName);
        if (mapping == null) {
            throw new IllegalArgumentException("Cannot find mapping: " + mappingName);
        }

        ArrayList<Mapping> maps = bindings.get(trigger.triggerHashCode());
        maps.remove(mapping);

    }

    /**
     * Clears all the input mappings from this InputManager. 
     * Consequently, also clears all of the
     * InputListeners as well.
     */
    public void clearMappings() {
        mappings.clear();
        bindings.clear();
        reset();
    }

    /**
     * Do not use.
     * Called to reset pressed keys or buttons when focus is restored.
     */
    public void reset() {
        pressedButtons.clear();
        axisValues.clear();
    }

    /**
     * Returns whether the mouse cursor is visible or not.
     * 
     * <p>By default the cursor is visible.
     * 
     * @return whether the mouse cursor is visible or not.
     * 
     * @see InputManager#setCursorVisible(boolean) 
     */
    public boolean isCursorVisible() {
        return mouseVisible;
    }

    /**
     * Set whether the mouse cursor should be visible or not.
     * 
     * @param visible whether the mouse cursor should be visible or not.
     */
    public void setCursorVisible(boolean visible) {
        if (mouseVisible != visible) {
            mouseVisible = visible;
            mouse.setCursorVisible(mouseVisible);
        }
    }

    /**
     * Returns the current cursor position. The position is relative to the
     * bottom-left of the screen and is in pixels.
     * 
     * @return the current cursor position
     */
    public Vector2f getCursorPosition() {
        return cursorPos;
    }

    /**
     * Returns an array of all joysticks installed on the system.
     * 
     * @return an array of all joysticks installed on the system.
     */
    public Joystick[] getJoysticks() {
        return joysticks;
    }

    /**
     * Adds a {@link RawInputListener} to receive raw input events.
     * 
     * <p>
     * Any raw input listeners registered to this <code>InputManager</code>
     * will receive raw input events first, before they get handled
     * by the <code>InputManager</code> itself. The listeners are 
     * each processed in the order they were added, e.g. FIFO.
     * <p>
     * If a raw input listener has handled the event and does not wish
     * other listeners down the list to process the event, it may set the
     * {@link InputEvent#setConsumed() consumed flag} to indicate the 
     * event was consumed and shouldn't be processed any further.
     * The listener may do this either at each of the event callbacks 
     * or at the {@link RawInputListener#endInput() } method.
     * 
     * @param listener A listener to receive raw input events.
     * 
     * @see RawInputListener
     */
    public void addRawInputListener(RawInputListener listener) {
        rawListeners.add(listener);
        rawListenerArray = null;
    }

    /**
     * Removes a {@link RawInputListener} so that it no longer
     * receives raw input events.
     * 
     * @param listener The listener to cease receiving raw input events.
     * 
     * @see InputManager#addRawInputListener(com.jme3.input.RawInputListener) 
     */
    public void removeRawInputListener(RawInputListener listener) {
        rawListeners.remove(listener);
        rawListenerArray = null;
    }

    /**
     * Clears all {@link RawInputListener}s.
     * 
     * @see InputManager#addRawInputListener(com.jme3.input.RawInputListener) 
     */
    public void clearRawInputListeners() {
        rawListeners.clear();
        rawListenerArray = null;
    }

    private RawInputListener[] getRawListenerArray() {
        if (rawListenerArray == null) 
            rawListenerArray = rawListeners.toArray(new RawInputListener[rawListeners.size()]);
        return rawListenerArray;
    }
    
    /**
     * Enable simulation of mouse events. Used for touchscreen input only.
     * 
     * @param value True to enable simulation of mouse events
     */
    public void setSimulateMouse(boolean value) {
        if (touch != null) {
            touch.setSimulateMouse(value);
        }
    }
    /**
     * Returns state of simulation of mouse events. Used for touchscreen input only.
     *
     */
    public boolean getSimulateMouse() {
        if (touch != null) {           
            return touch.getSimulateMouse();
        } else {
            return false;
        }
    }
    
    /**
     * Enable simulation of keyboard events. Used for touchscreen input only.
     * 
     * @param value True to enable simulation of keyboard events
     */
    public void setSimulateKeyboard(boolean value) {
        if (touch != null) {
            touch.setSimulateKeyboard(value);
        }
    }

    private void processQueue() {
        int queueSize = inputQueue.size();
        RawInputListener[] array = getRawListenerArray();
 
        for (RawInputListener listener : array) {
            listener.beginInput();

            for (int j = 0; j < queueSize; j++) {
                InputEvent event = inputQueue.get(j);
                if (event.isConsumed()) {
                    continue;
                }

                if (event instanceof MouseMotionEvent) {
                    listener.onMouseMotionEvent((MouseMotionEvent) event);
                } else if (event instanceof KeyInputEvent) {
                    listener.onKeyEvent((KeyInputEvent) event);
                } else if (event instanceof MouseButtonEvent) {
                    listener.onMouseButtonEvent((MouseButtonEvent) event);
                } else if (event instanceof JoyAxisEvent) {
                    listener.onJoyAxisEvent((JoyAxisEvent) event);
                } else if (event instanceof JoyButtonEvent) {
                    listener.onJoyButtonEvent((JoyButtonEvent) event);
                } else if (event instanceof TouchEvent) {
                    listener.onTouchEvent((TouchEvent) event);
                } else {
                    assert false;
                }
            }

            listener.endInput();
        }

        for (int i = 0; i < queueSize; i++) {
            InputEvent event = inputQueue.get(i);
            if (event.isConsumed()) {
                continue;
            }

            if (event instanceof MouseMotionEvent) {
                onMouseMotionEventQueued((MouseMotionEvent) event);
            } else if (event instanceof KeyInputEvent) {
                onKeyEventQueued((KeyInputEvent) event);
            } else if (event instanceof MouseButtonEvent) {
                onMouseButtonEventQueued((MouseButtonEvent) event);
            } else if (event instanceof JoyAxisEvent) {
                onJoyAxisEventQueued((JoyAxisEvent) event);
            } else if (event instanceof JoyButtonEvent) {
                onJoyButtonEventQueued((JoyButtonEvent) event);
            } else if (event instanceof TouchEvent) {
                onTouchEventQueued((TouchEvent) event);
            } else {
                assert false;
            }
            // larynx, 2011.06.10 - flag event as reusable because
            // the android input uses a non-allocating ringbuffer which
            // needs to know when the event is not anymore in inputQueue
            // and therefor can be reused.
            event.setConsumed();
        }

        inputQueue.clear();
    }

    /**
     * Updates the <code>InputManager</code>. 
     * This will query current input devices and send
     * appropriate events to registered listeners.
     *
     * @param tpf Time per frame value.
     */
    public void update(float tpf) {
        frameTPF = tpf;
        
        // Activate safemode if the TPF value is so small
        // that rounding errors are inevitable
        safeMode = tpf < 0.015f;
        
        long currentTime = keys.getInputTimeNanos();
        frameDelta = currentTime - lastUpdateTime;

        eventsPermitted = true;

        keys.update();
        mouse.update();
        if (joystick != null) {
            joystick.update();
        }
        if (touch != null) {
            touch.update();
        }

        eventsPermitted = false;

        processQueue();
        invokeUpdateActions();

        lastLastUpdateTime = lastUpdateTime;
        lastUpdateTime = currentTime;
    }

    /**
     * Dispatches touch events to touch listeners
     * @param evt The touch event to be dispatched to all onTouch listeners
     */
    public void onTouchEventQueued(TouchEvent evt) { 
        ArrayList<Mapping> maps = bindings.get(TouchTrigger.touchHash(evt.getKeyCode()));
        if (maps == null) {
            return;
        }

        int size = maps.size();
        for (int i = size - 1; i >= 0; i--) {
            Mapping mapping = maps.get(i);
            ArrayList<InputListener> listeners = mapping.listeners;
            int listenerSize = listeners.size();
            for (int j = listenerSize - 1; j >= 0; j--) {
                InputListener listener = listeners.get(j);
                if (listener instanceof TouchListener) {
                    ((TouchListener) listener).onTouch(mapping.name, evt, frameTPF); 
                }
            }
        }               
    }
    
    /**
     * Callback from RawInputListener. Do not use.
     */
    @Override
    public void onTouchEvent(TouchEvent evt) {
        if (!eventsPermitted) {
            throw new UnsupportedOperationException("TouchInput has raised an event at an illegal time.");
        }
        inputQueue.add(evt);         
    }
}
