using UnityEngine;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using SC.XR.Unity.Module_InputSystem;

public class RollList : BaseList, IDragHandler, IPointerEnterHandler, IPointerExitHandler, IPointerUpHandler, IPointerDownHandler
{
    private float moveTime=0.2f;
    public List<GameObject> controlPoints;
    //  public LineRenderer lineRenderer;
    public bool isFixed;
    Vector3 v1;
    Vector3 v2;
    Vector3 v3;
    [HideInInspector]
    private int startItem = 0;
    [HideInInspector]
    private int endItem = 0;
    //private j
    private float speedTime = 0;
    private float dragTime = 0.2f;
    private float clickTime = 0.2f;
    private float lastClickTime;
    private float lastDragTime;
    public virtual void Update()
    {
        if (isJiasudu)
        {
            speedTime = speedTime + Time.deltaTime;
            if(speedTime>3)
            {
                speedTime = 0;
                isJiasudu = false;
                fixedItems();
            }
            jiasudu = jiasudu / 1.4f;
            Move(jiasudu);
        }
        DrawCurve();
        if(eventEnterData!=null)
        {
            RollView rv = OnCheckView(eventEnterData);
            if(rv==null&& chooseView!=null)
            {
                chooseView.OnPointerExit(eventEnterData);
               // chooseView = null;
            }
            if (chooseView != rv&& chooseView!=null)
            {
                if (rv != null)
                {
                    chooseView.OnPointerExit(eventEnterData);
                    chooseView = rv;
                    chooseView.OnPointerEnter(eventEnterData);

                }
            };
        }
    }

    public override void initList(List<BaseConfig> c)
    {
        base.initList(c);
        DrawCurve();
        Column = 1;
        startItem = 0;
        endItem = Row * Column;
    }

    float time = 1f;
    void Move(float f)
    {
        if (Mathf.Abs(f) >= 1)
        {
            if (f > 0)
            {
                f = 1;
            }
            else
            {
                f = -1;
            }
        }
        if (Mathf.Abs(f) <= 1)
        {
            for (int i = 0; i < Views.Count; i++)
            {
                if (f > 0)
                {

                    if (i + 1 < Views.Count)
                    {
                        //  LeanTween.moveLocal(itemView[i], pos[i+1], time);
                       // Views[i].transform.localPosition = Vector3.Lerp(Views[i].transform.localPosition, pos[i + 1], Mathf.Abs(f));
                        Views[i].transform.localPosition = Views[i].transform.localPosition + (pos[i + 1] - Views[i].transform.localPosition) * f;
                      //  Views[i].gameObject.SetActive(true);
                    }
                    else
                    {
                        Views[i].transform.localPosition = Views[i].transform.localPosition + (pos[i + 1] - Views[i].transform.localPosition) * f;

                        //  Views[i].gameObject.SetActive(false);
                    }
                }
                else
                {


                    if ((i - 1) >= 0)
                    {
                        Views[i].transform.localPosition = Views[i].transform.localPosition - (pos[i - 1] - Views[i].transform.localPosition) * f;

                        //  Views[i].gameObject.SetActive(true);
                    }
                    else
                    {
                        Views[i].transform.localPosition = Views[i].transform.localPosition - (pos[i - 1] - Views[i].transform.localPosition) * f;

                        //  Views[i].gameObject.SetActive(false);
                    }
                }
            }
        }
        if (f > 0)
        {
            if (Vector3.Distance(Views[0].transform.localPosition, pos[1]) < (Vector3.Distance(pos[0], pos[1]) / 10))
            {
                moveRightEnd();
            }

        }
        else if (f < 0)
        {
            if (Vector3.Distance(Views[1].transform.localPosition, pos[0]) < (Vector3.Distance(pos[0], pos[1]) / 10))
            {
                moveleftEnd();
            }

        }
        // Invoke("moveEnd", time);
    }

    void getShowItem()
    {
        List<int> showItemS = new List<int>();
        int ct=0;
        int vCt = 0;
        if (Views.Count > configs.Count)
        {
            vCt = Views.Count;
        }
        else
        {
            vCt = configs.Count;

        }
     //   Debug.Log("滚动次数===》"+ rCount);
        for (int i = rCount; i < Views.Count+ rCount; i++)
        {
            ct = i;
            if (i<0)
            {
                ct = vCt - Mathf.Abs(i);
            }
            else if(i >= vCt)
            {
                ct = i - vCt;
            }
         //   Debug.Log(ct);
            showItemS.Add(ct);
        }
        showItems(showItemS);
    }

    void moveleftEnd(bool Tween=false)
    {
        rCount++;
        if(Mathf.Abs(rCount)>=configs.Count)
        {
            rCount = 0;
        }
        List<BaseView> controlPoints2 = new List<BaseView>();
        Views[0].transform.localPosition = pos[Views.Count - 1]; 
        for (int i = 0; i < Views.Count; i++)
        {
            if (i == (Views.Count - 1))
            {
                if(Tween)
                {
                    LeanTween.moveLocal(Views[0].gameObject, pos[i], moveTime);

                }
                else
                {
                    Views[0].transform.localPosition = pos[i];

                }
                controlPoints2.Add(Views[0]);
            }
            else
            {
                if (Tween)
                {
                    LeanTween.moveLocal(Views[i + 1].gameObject, pos[i], moveTime);
                }
                else
                {

                    Views[i + 1].transform.localPosition = pos[i];
                }
                controlPoints2.Add(Views[i + 1]);
            }
        }
        Views = controlPoints2;
        controlPoints2[Views.Count - 1].gameObject.SetActive(true);
        getShowItem();
        // Move();
    }

     
    void moveRightEnd(bool Tween = false)
    {
        rCount--;
        if (Mathf.Abs(rCount) >= configs.Count)
        {
            rCount = 0;
        }
        List<BaseView> controlPoints2 = new List<BaseView>();
        Views[Views.Count - 1].transform.localPosition = pos[0];
        for (int i = 0; i < Views.Count; i++)
        {
            if (i == 0)
            {
                if (Tween)
                {
                    LeanTween.moveLocal(Views[Views.Count - 1].gameObject, pos[i], moveTime);
                }else
                {
                    Views[Views.Count - 1].transform.localPosition = pos[i];

                }
                controlPoints2.Add(Views[Views.Count - 1]);
            }
            else
            {

                if (Tween)
                {
                   LeanTween.moveLocal(Views[i - 1].gameObject, pos[i], moveTime);
                }
                else
                {
                    Views[i - 1].transform.localPosition = pos[i];
                }
                controlPoints2.Add(Views[i - 1]);
            }
        }
        Views = controlPoints2;
        controlPoints2[0].gameObject.SetActive(true);
        getShowItem();
    }
    bool isStart=false;
    public Dictionary<int, Vector3> pos = new Dictionary<int, Vector3>();
   // List<Vector3> pos = new List<Vector3>();
    void DrawCurve()
    {
        if (controlPoints.Count > 0)
        {
            v1 = controlPoints[0].transform.localPosition;
            v2 = controlPoints[1].transform.localPosition;
            v3 = controlPoints[2].transform.localPosition;
            pos = new Dictionary<int, Vector3>();
            int count = -1;
            for (int i = 0; i < Row+2; i++)
            {
                float t = i / ((float)Row+2);
                Vector3 pixel = CalculateCubicBezierPoint(t, v1, v2, v3);
                pos.Add(count, pixel);
                if (!isStart&& Views.Count>(i-1)&&i>=1)
                    Views[i-1].transform.localPosition = pos[count];

                count++;
                //   itemView[i].transform.localPosition = pixel;
            }
        }
        isStart = true;

    }

    Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
    {
        float u = 1 - t;
        float tt = t * t;
        float uu = u * u;

        Vector3 p = uu * p0;
        p += 2 * u * t * p1;
        p += tt * p2;

        return p;
    }
    bool isMove;
    private Vector3 startPos;
    private float oldNum=0;
    public virtual void OnDrag(PointerEventData eventData)
    {
        if ((Time.time - lastClickTime) < clickTime)
        {
            return;
        }
        isMove = true;
        SCPointEventData sCPointEventData = eventData as SCPointEventData;
        float num = 0;
        Vector3 pos3d = sCPointEventData.Position3D / this.transform.localScale.x;
        num = (startPos.x - pos3d.x);

        num = Vector3.Cross(this.transform.forward, pos3d).y- oldNum;
        oldNum = Vector3.Cross(this.transform.forward, pos3d).y;

        Vector3 a = GSXRManager.Instance.leftCamera.WorldToScreenPoint(startScreenV3);
        Vector3 b = GSXRManager.Instance.leftCamera.WorldToScreenPoint(sCPointEventData.Position3D);
        num = (a - b).x;
        startPos = pos3d;
        startScreenV3 = sCPointEventData.Position3D;
        if(Mathf.Abs(num)>10)
        {
            if(num>0)
            num = 10;
            else
            {
                num = -10;
            }
        }
        else if(Mathf.Abs(num) < 2f)
        {

            num = 0;
        }
        Move(-num / 50);
        jTime = jTime + Time.deltaTime;
        if(jTime>0.3f)
        {
            jTime = 0;
            jiasudu = 0;
        }
        else
        {
            jiasudu = jiasudu - num/50;
        }
    }
    PointerEventData eventEnterData;
    public virtual void OnPointerEnter(PointerEventData eventData)
    {
        eventEnterData = eventData;
        chooseView =  OnCheckView(eventData);
        if(chooseView!=null)
        chooseView.OnPointerEnter(eventData);
    }

    public virtual void OnPointerExit(PointerEventData eventData)
    {
        eventEnterData = null;
        if (chooseView!=null)
        {
            chooseView.OnPointerExit(eventData);
            chooseView = null;
        }
    }

    public RollView OnCheckView(PointerEventData eventData)
    {
        if(isMove)
        {
            return null;
        }
        SCPointEventData sCPointEventData = eventData as SCPointEventData;
        Vector3 v3event = sCPointEventData.inputDevicePartBase.detectorBase.pointerBase.cursorBase.transform.position;
        RollView baseView = null;
        float distanceMin=10;
        for (int i = 0; i < Views.Count; i++)
        {
            Vector3 v3 = this.transform.InverseTransformPoint(Views[i].transform.position);
            v3 = new Vector3(v3.x, v3.y, 0);
            v3 = this.transform.TransformPoint(v3);
            float disView = Vector3.Distance(v3event, v3);

            if(distanceMin> disView)
            {
                distanceMin = disView;
                baseView =(RollView)Views[i];
            }
        }
        return baseView;
    }

    public virtual void OnPointerUp(PointerEventData eventData)
    {
        if (jiasudu!=0)
            isJiasudu = true;
        else
        {
            fixedItems();
        }
        if (Time.time - lastDragTime < dragTime)
        {
            if (eventData.pointerEnter)
            {
                var tmpbutton = eventData.pointerEnter.GetComponentInParent<IPointerClickHandler>();
                if (tmpbutton != null)
                {
                    tmpbutton.OnPointerClick(eventData);
                }
            }
        }
        if (chooseView != null)
        {
            if ((Time.time - lastClickTime)< clickTime)
            {
                chooseView.OnClick(eventData);
            }
            chooseView.OnPointerUp(eventData);
          //  chooseView = null;

        }
        isMove = false;
    }

    private void fixedItems()
    {
        if(isFixed&&!isJiasudu)
        {
            if (Vector3.Distance(Views[1].transform.localPosition, pos[1]) > Vector3.Distance(pos[1], pos[2])/2f)
            {
                moveleftEnd(true);
            }
            if (Vector3.Distance(Views[1].transform.localPosition, pos[1]) > Vector3.Distance(pos[0], pos[1]) / 2f)
            {
                moveRightEnd(true);

            }
            else
            {
                //   Debug.Log("滚动次数===》"+ rCount);
                for (int i = 0; i < Views.Count; i++)
                {
                    LeanTween.moveLocal(Views[i].gameObject, pos[i], 0.3f);
                    //Views[i].transform.localPosition = pos[i];
                }

            }
        }
    }

    private float jiasudu;
    private float jTime;
    private bool isJiasudu;
    private Vector3 startScreenV3;

    private RollView chooseView;
    public virtual void OnPointerDown(PointerEventData eventData)
    {
        SCPointEventData sCPointEventData = eventData as SCPointEventData;
        Vector3 pos3d = sCPointEventData.Position3D / this.transform.localScale.x;
        startScreenV3 = sCPointEventData.Position3D;
        //   num = Vector3.Cross(this.transform.forward, pos3d).y;
        startPos = pos3d;
        isJiasudu = false;
        speedTime = 0;
        lastDragTime = Time.time;
        lastClickTime = Time.time;
        chooseView = OnCheckView(eventData);
        if(chooseView!=null)
        chooseView.OnPointerDown(eventData);
    }


    public override void updateConfig(List<BaseConfig> c)
    {
        base.updateConfig(c);
        if (this.configs.Count < c.Count)
        {
            configs = new List<BaseConfig>();
            c.ForEach(i => configs.Add(i));
            if(c.Count> Views.Count)
            {
                rCount = c.Count - Views.Count;
            }
            getShowItem();
        }
        else if(rCount>(c.Count - 1))
        {
            configs = new List<BaseConfig>();
            c.ForEach(i => configs.Add(i));
            if (c.Count > Views.Count)
            {
                rCount = c.Count - Views.Count;
            }
            getShowItem();
        }
        else
        {
            configs = new List<BaseConfig>();
            c.ForEach(i => configs.Add(i));
            getShowItem();
        }

    }

}
public class BezierUtils
{
    /// <summary>
    /// 根据T值,计算贝塞尔曲线上面相对应的点
    /// </summary>
    /// <param name="t"></param>T值
    /// <param name="p0"></param>起始点
    /// <param name="p1"></param>控制点
    /// <param name="p2"></param>目标点
    /// <returns></returns>根据T值计算出来的贝赛尔曲线点
    private static Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
    {
        float u = 1 - t;
        float tt = t * t;
        float uu = u * u;

        Vector3 p = uu * p0;
        p += 2 * u * t * p1;
        p += tt * p2;

        return p;
    }

    /// <summary>
    /// 获取存储贝塞尔曲线点的数组
    /// </summary>
    /// <param name="startPoint"></param>起始点
    /// <param name="controlPoint"></param>控制点
    /// <param name="endPoint"></param>目标点
    /// <param name="segmentNum"></param>采样点的数量
    /// <returns></returns>存储贝塞尔曲线点的数组
    public static Vector3[] GetBeizerList(Vector3 startPoint, Vector3 controlPoint, Vector3 endPoint, int segmentNum)
    {
        Vector3[] path = new Vector3[segmentNum];
        for (int i = 1; i <= segmentNum; i++)
        {
            float t = i / (float)segmentNum;
            Vector3 pixel = CalculateCubicBezierPoint(t, startPoint,
                controlPoint, endPoint);
            path[i - 1] = pixel;
            Debug.Log(path[i - 1]);
        }
        return path;

    }

 }