/**
 * Contains the GesturesObserver class, which lets you observe and respond to user gestures
 */
declare module "ui/gestures" {
    import view = require("ui/core/view");
    import observable = require("data/observable");

    /**
     * Defines an enum with supported gesture types.
     */
    export enum GestureTypes {
        /**
         * Denotes tap (click) gesture.
         */
        tap,
        /**
         * Denotes double tap gesture.
         */
        doubleTap,
        /**
         * Denotes pinch gesture.
         */
        pinch,
        /**
         * Denotes pan gesture.
         */
        pan,
        /**
         * Denotes swipe gesture.
         */
        swipe,
        /**
         * Denotes rotation gesture.
         */
        rotation,
        /**
         * Denotes long press gesture.
         */
        longPress,
        /**
         * Denotes touch action.
         */
        touch
    }

    /**
     * Defines an enum with supported gesture types.
     */
    export enum GestureStateTypes {
        /**
         * Gesture canceled.
         */
        cancelled,
        /**
         * Gesture began.
         */
        began,
        /**
         * Gesture changed.
         */
        changed,
        /**
         * Gesture ended.
         */
        ended
    }

    /**
     * Defines an enum for swipe gesture direction.
     */
    export enum SwipeDirection {
        /**
         * Denotes right direction for swipe gesture.
         */
        right,
        /**
         * Denotes left direction for swipe gesture.
         */
        left,
        /**
         * Denotes up direction for swipe gesture.
         */
        up,
        /**
         * Denotes down direction for swipe gesture.
         */
        down
    }

    /**
     * Defines a touch action
     */
    export module TouchAction {
        /**
         * Down action.
         */
        export var down: string;

        /**
         * Up action.
         */
        export var up: string;
        
        /**
         * Move action.
         */
        export var move: string;
        
        /**
         * Cancel action.
         */
        export var cancel: string;
    }

    /**
     * Provides gesture event data.
     */
    export interface GestureEventData extends observable.EventData {
        /**
         * Gets the type of the gesture.
         */
        type: GestureTypes;
        /**
         * Gets the view which originates the gesture.
         */
        view: view.View;
        /**
         * Gets the underlying native iOS specific [UIGestureRecognizer](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIGestureRecognizer_Class/).
         */
        ios: any /* UIGestureRecognizer */;
        /**
         * Gets the underlying native android specific [gesture detector](http://developer.android.com/reference/android/view/GestureDetector.html).
         */
        android: any
    }

    /**
     * Provides gesture event data.
     */
    export interface TouchGestureEventData extends GestureEventData {
        /**
         * Gets action of the touch. Possible values: 'up', 'move', 'down', 'cancel'
         */
        action: string;

        /**
         * Gets the X coordinate of this event inside the view that triggered the event.
         */
        getX(): number;

        /**
         * Gets the Y coordinate of this event inside the view that triggered the event.
         */
        getY(): number;
        
        /**
         * Gets the number of pointers in the event.
         */
        getPointerCount(): number;

        /**
         * Gets the pointers that triggered the event.
         * Note: In Android there is aways only one active pointer.
         */
        getActivePointers(): Array<Pointer>;

        /**
         * Gets all pointers.
         */
        getAllPointers(): Array<Pointer>;
    }

    /**
     * Pointer is an object representing a finger (or other object) that is touching the screen.
     */
    export interface Pointer {
        /**
         * The id of the pointer.
         */
        android: any;

        /**
         * The UITouch object associated to the touch
         */
        ios: any;

        /**
         * Gets the X coordinate of the pointer inside the view that triggered the event.
         */
        getX(): number;

        /**
         * Gets the Y coordinate of the pointer inside the view that triggered the event.
         */
        getY(): number;
    }

    /**
     * Provides gesture event data for pinch gesture.
     */
    export interface GestureEventDataWithState extends GestureEventData {
        state: number;
    }

    /**
     * Provides gesture event data for pinch gesture.
     */
    export interface PinchGestureEventData extends GestureEventDataWithState {
        scale: number;

        getFocusX(): number;
        getFocusY(): number;
    }

    /**
     * Provides gesture event data for swipe gesture.
     */
    export interface SwipeGestureEventData extends GestureEventData {
        direction: SwipeDirection;
    }

    /**
     * Provides gesture event data for pan gesture.
     */
    export interface PanGestureEventData extends GestureEventDataWithState {
        deltaX: number;
        deltaY: number;
    }

    /**
     * Provides gesture event data for rotation gesture.
     */
    export interface RotationGestureEventData extends GestureEventDataWithState {
        rotation: number;
    }

    /**
     * Provides options for the GesturesObserver.
     */
    export class GesturesObserver {
        /**
         * Creates an instance of GesturesObserver class.
         * @param target - The view for which the observer is created.
         * @param callback - A function that will be executed when a gesture is received.
         * @param context - default this argument for the callbacks.
         */
        constructor(target: view.View, callback: (args: GestureEventData) => void, context: any);

        /**
         * Registers a gesture observer to a view and gesture.
         * @param type - Type of the gesture.
         */
        observe(type: GestureTypes);

        /**
         * Disconnects the gesture observer.
         */
        disconnect();

        /**
         * Gesture type attached to the observer.
         */
        type: GestureTypes;

        /**
         * A function that will be executed when a gesture is received.
         */
        callback: (args: GestureEventData) => void;

        /**
         * A context which will be used as `this` in callback execution.
         */
        context: any;

        /**
         * An internal Android specific method used to pass the motion event to the correct gesture observer.
         */
        androidOnTouchEvent: (motionEvent: any /* android.view.MotionEvent */) => void;
    }

    /**
     * A short-hand function that is used to create a gesture observer for a view and gesture.
     * @param target - View which will be watched for originating a specific gesture.
     * @param type - Type of the gesture.
     * @param callback - A function that will be executed when a gesture is received.
     * @param context - this argument for the callback.
     */
    export function observe(target: view.View, type: GestureTypes, callback: (args: GestureEventData) => void, context?: any): GesturesObserver;

    /**
     * Returns a string representation of a gesture type.
     * @param type - Type of the gesture.
     * @param separator(optional) - Text separator between gesture type strings.
     */
    export function toString(type: GestureTypes, separator?: string): string;

    /**
     * Returns a gesture type enum value from a string (case insensitive).
     * @param type - A string representation of a gesture type (e.g. Tap).
     */
    export function fromString(type: string): GestureTypes;
}
