import { ViewController } from './ctr';
export function getHorizontalDirection(angle) {
    angle += 90;
    return Math.floor((angle % 360) / 180) + 1;
}
export function getVerticalDirection(angle) {
    return Math.floor((angle % 360) / 180) + 1;
}
function get_angle(p1, p2) {
    var arc = Math.atan2(p1.y - p2.y, p2.x - p1.x);
    var angle = (arc / Math.PI * 180 + 360) % 360;
    return angle;
}
function get_direction(angle) {
    angle += 45;
    return Math.floor((angle % 360) / 90) + 1;
}
function get_distance(p1, p2) {
    var x = Math.abs(p1.x - p2.x);
    var y = Math.abs(p1.y - p2.y);
    return Math.sqrt(x ** 2 + y ** 2);
}
function has_speed_invalid(time0, time1) {
    if (!time0 || !time1 || time1 - time0 > 300) {
        return true;
    }
    return false;
}
function compute_speed(time0, time1, speed0, distance) {
    if (has_speed_invalid(time0, time1)) {
        return { speed: 0, instant_speed: 0 };
    }
    var instant_speed = distance / ((time1 - time0) / 1000);
    return {
        speed: (speed0 + instant_speed) / 2,
        instant_speed,
    };
}
export var Direction;
(function (Direction) {
    Direction[Direction["LEFT"] = 1] = "LEFT";
    Direction[Direction["TOP"] = 2] = "TOP";
    Direction[Direction["RIGHT"] = 3] = "RIGHT";
    Direction[Direction["BOTTOM"] = 4] = "BOTTOM";
})(Direction || (Direction = {}));
export default class Gesture extends ViewController {
    constructor() {
        super(...arguments);
        this._identifier = -1;
        this._begin_x = 0;
        this._begin_y = 0;
        this._x = 0;
        this._y = 0;
        this._speed = 0;
        this._time = 0;
        this._ev = null;
        this._begin = false;
        this._begin_angle = 0;
        this._begin_direction = 0;
    }
    get clientWidth() {
        return this.$el.clientWidth;
    }
    get clientHeight() {
        return this.$el.clientHeight;
        ;
    }
    static _selectTouch(self, e) {
        if (self._identifier != -1) {
            return Array.toArray(e.changedTouches).find(e => {
                if (e.identifier == self._identifier) {
                    return e;
                }
            });
        }
    }
    static _handleBegin(self, e) {
        var { x, y } = e;
        var time = Date.now();
        self._begin_x = x;
        self._begin_y = y;
        self._x = x;
        self._y = y;
        self._time = time;
        self._speed = 0;
        self._begin = false;
        var ev = {
            begin: true,
            time: time,
            begin_x: x, begin_y: y,
            prev_x: x, prev_y: x,
            x: y, y: y,
            speed: 0, instant_speed: 0,
            begin_angle: 0, angle: 0, instant_angle: 0,
            begin_direction: 0, direction: 0,
            instant_direction: 0,
            distance: 0, instant_distance: 0, cancelBubble: false,
        };
        self.triggerBeginMove(ev);
        return ev.cancelBubble;
    }
    static _handleMove(self, e) {
        var { x, y } = e;
        var prev_time = self._time;
        var time = Date.now();
        var p1 = { x: self._begin_x, y: self._begin_y };
        var p2 = { x: self._x, y: self._y };
        var p3 = { x, y };
        var angle = get_angle(p1, p3);
        var instant_angle = get_angle(p2, p3);
        var direction = get_direction(angle);
        var instant_direction = get_direction(instant_angle);
        var distance = get_distance(p1, p2);
        var instant_distance = get_distance(p2, p3);
        var { speed, instant_speed } = compute_speed(prev_time, time, self._speed, instant_distance);
        var begin_angle = self._begin_angle;
        var begin_direction = self._begin_direction;
        if (!self._begin) {
            self._begin_angle = begin_angle = angle;
            self._begin_direction = begin_direction = direction;
        }
        self._x = x;
        self._y = y;
        self._time = time;
        self._speed = speed;
        var ev = {
            begin: !self._begin,
            time: time,
            begin_x: self._begin_x,
            begin_y: self._begin_y,
            prev_x: p2.x, prev_y: p2.y,
            x, y,
            speed, instant_speed,
            begin_angle, angle, instant_angle,
            begin_direction, direction, instant_direction,
            distance, instant_distance, cancelBubble: false,
        };
        self._ev = { ...ev };
        self._begin = true;
        self.triggerMove(ev);
        return ev.cancelBubble;
    }
    static _handleEnd(self, e) {
        var ev = self._ev;
        var time = Date.now();
        if (ev) {
            if (has_speed_invalid(ev.time, time)) {
                Object.assign(ev, {
                    speed: 0, instant_speed: 0,
                });
            }
        }
        else {
            var { x, y } = e;
            ev = {
                begin: false,
                time: time,
                begin_x: x, begin_y: y,
                prev_x: x, prev_y: x,
                x: y, y: y,
                speed: 0, instant_speed: 0,
                begin_angle: 0, angle: 0, instant_angle: 0,
                begin_direction: 0, direction: 0, instant_direction: 0,
                distance: 0, instant_distance: 0, cancelBubble: false,
            };
        }
        ev.begin = false;
        self.triggerEndMove(ev);
        self._time = 0;
        self._speed = 0;
        self._ev = null;
        self._begin = false;
        self._begin_angle = 0;
        self._begin_x = self._begin_y = self._x = self._y = 0;
        return ev.cancelBubble;
    }
    static _handleTouchstart(self, e) {
        if (self._identifier == -1) {
            var touch = e.changedTouches[0];
            self._identifier = touch.identifier;
            if (Gesture._handleBegin(self, { x: touch.pageX, y: touch.pageY })) {
                e.stopPropagation();
            }
        }
    }
    static _handleTouchmove(self, e) {
        var touch = Gesture._selectTouch(self, e);
        if (touch) {
            if (Gesture._handleMove(self, { x: touch.pageX, y: touch.pageY })) {
                e.stopPropagation();
            }
        }
    }
    static _handleTouchend(self, e) {
        var touch = Gesture._selectTouch(self, e);
        if (touch) {
            if (Gesture._handleEnd(self, { x: touch.pageX, y: touch.pageY })) {
                e.stopPropagation();
            }
            self._identifier = -1;
        }
    }
    static _handleMousedown(self, e) {
        if (self._identifier == -1) {
            self._identifier = 1;
            if (Gesture._handleBegin(self, { x: e.pageX, y: e.pageY })) {
                e.stopPropagation();
            }
        }
    }
    static _handleMousemove(self, e) {
        if (self._identifier == 1) {
            if (Gesture._handleMove(self, { x: e.pageX, y: e.pageY })) {
                e.stopPropagation();
            }
        }
    }
    static _handleMouseup(self, e) {
        if (self._identifier == 1) {
            if (Gesture._handleEnd(self, { x: e.pageX, y: e.pageY })) {
                e.stopPropagation();
            }
            self._identifier = -1;
        }
    }
    triggerMounted() {
        var el = this.$el;
        if ('ontouchstart' in globalThis.document.body) {
            el.addEventListener('touchstart', (e) => Gesture._handleTouchstart(this, e));
            el.addEventListener('touchmove', e => Gesture._handleTouchmove(this, e));
            el.addEventListener('touchend', e => Gesture._handleTouchend(this, e));
        }
        else {
            el.addEventListener('mousedown', (e) => Gesture._handleMousedown(this, e));
            el.addEventListener('mousemove', (e) => Gesture._handleMousemove(this, e));
            el.addEventListener('mouseup', (e) => Gesture._handleMouseup(this, e));
        }
    }
    triggerBeginMove(e) { }
    triggerMove(e) { }
    triggerEndMove(e) { }
}
