using System;
using System.Collections.Generic;
using UnityEngine;
namespace FairyGUI
{
    /// 
    /// 长按手势。当按下一定时间后(duration),派发onAction,如果once为false,则间隔duration时间持续派发onAction,直到手指释放。
    /// 
    public class LongPressGesture : EventDispatcher
    {
        /// 
        /// 
        /// 
        public GObject host { get; private set; }
        /// 
        /// 当手指按下时派发该事件。
        /// 
        public EventListener onBegin { get; private set; }
        /// 
        /// 手指离开屏幕时派发该事件。
        /// 
        public EventListener onEnd { get; private set; }
        /// 
        /// 当手指按下后一段时间后派发该事件。并且在手指离开前按一定周期派发该事件。
        /// 
        public EventListener onAction { get; private set; }
        /// 
        /// 第一次派发事件的触发时间。单位秒
        /// 
        public float trigger;
        /// 
        /// 派发onAction事件的时间间隔。单位秒。
        /// 
        public float interval;
        /// 
        /// 如果为真,则onAction再一次按下释放过程只派发一次。如果为假,则每隔duration时间派发一次。
        /// 
        public bool once;
        /// 
        /// 手指按住后,移动超出此半径范围则手势停止。
        /// 
        public int holdRangeRadius;
        Vector2 _startPoint;
        bool _started;
        int _touchId;
        public static float TRIGGER = 1.5f;
        public static float INTERVAL = 1f;
        public LongPressGesture(GObject host)
        {
            this.host = host;
            trigger = TRIGGER;
            interval = INTERVAL;
            holdRangeRadius = 50;
            Enable(true);
            onBegin = new EventListener(this, "onLongPressBegin");
            onEnd = new EventListener(this, "onLongPressEnd");
            onAction = new EventListener(this, "onLongPressAction");
        }
        public void Dispose()
        {
            Enable(false);
            host = null;
        }
        public void Enable(bool value)
        {
            if (value)
            {
                if (host == GRoot.inst)
                {
                    Stage.inst.onTouchBegin.Add(__touchBegin);
                    Stage.inst.onTouchEnd.Add(__touchEnd);
                }
                else
                {
                    host.onTouchBegin.Add(__touchBegin);
                    host.onTouchEnd.Add(__touchEnd);
                }
            }
            else
            {
                if (host == GRoot.inst)
                {
                    Stage.inst.onTouchBegin.Remove(__touchBegin);
                    Stage.inst.onTouchEnd.Remove(__touchEnd);
                }
                else
                {
                    host.onTouchBegin.Remove(__touchBegin);
                    host.onTouchEnd.Remove(__touchEnd);
                }
                Timers.inst.Remove(__timer);
            }
        }
        public void Cancel()
        {
            Timers.inst.Remove(__timer);
            _started = false;
        }
        void __touchBegin(EventContext context)
        {
            InputEvent evt = context.inputEvent;
            _startPoint = host.GlobalToLocal(new Vector2(evt.x, evt.y));
            _started = false;
            _touchId = evt.touchId;
            Timers.inst.Add(trigger, 1, __timer);
            context.CaptureTouch();
        }
        void __timer(object param)
        {
            Vector2 pt = host.GlobalToLocal(Stage.inst.GetTouchPosition(_touchId));
            if (Mathf.Pow(pt.x - _startPoint.x, 2) + Mathf.Pow(pt.y - _startPoint.y, 2) > Mathf.Pow(holdRangeRadius, 2))
            {
                Timers.inst.Remove(__timer);
                return;
            }
            if (!_started)
            {
                _started = true;
                onBegin.Call();
                if (!once)
                    Timers.inst.Add(interval, 0, __timer);
            }
            onAction.Call();
        }
        void __touchEnd(EventContext context)
        {
            Timers.inst.Remove(__timer);
            if (_started)
            {
                _started = false;
                onEnd.Call();
            }
        }
    }
}