using System;
using System.Collections.Generic;
using UnityEngine;

namespace Thousandto.Cinematic.Plugin
{
    public  class CinematicUI_Curve : MonoBehaviour
    {
        public List<GameObject> GameObjectList;
        public int CurvRate = 20;
        public int Offset = 2;
        public bool UseSlider = false;
        public float SliderValue = 0;

        public CinematicObj CinematicObj;

        private static int _offset = 2;
        private static int _rate = 20;
        private static bool _userSlider;

        private List<Vector3> _transDataList = new List<Vector3>();
        private List<CinematicKeyframe> _transKeyframeList = new List<CinematicKeyframe>();

        void Start()
        {
            InitTransformData();
        }

        void InitTransformData()
        {
            if(CinematicObj != null)
            {
                _transDataList.Clear();
                for (int i = 0; i < CinematicObj.KeyframeList.Count; ++i)
                {
                    bool hasSyncEvent = false;
                    bool hasPosition = false;
                    Vector3 position = Vector3.zero;
                    for(int m = 0; m < CinematicObj.KeyframeList[i].EventData.Count; ++m)
                    {
                        var eventData = CinematicObj.KeyframeList[i].EventData[m];
                        if (eventData.EventTypeEx == KeyFrameEvent.坐标变换)
                        {
                            hasPosition = true;
                            position = eventData.Position;
                            //_transDataList.Add(eventData.Position);
                            _transKeyframeList.Add(CinematicObj.KeyframeList[i]);
                        }
                        if (eventData.EventTypeEx == KeyFrameEvent.同步到本地相机坐标 ||
                            eventData.EventTypeEx == KeyFrameEvent.同步到本地角色坐标)
                            hasSyncEvent = true;
                    }

                    if(!hasSyncEvent && hasPosition)
                        _transDataList.Add(position);
                }
            }
        }

        public void OnRefresh()
        {
            InitTransformData();
        }

        void OnDrawGizmos()
        {
            _rate = CurvRate;
            _offset = Offset;
            _userSlider = UseSlider;

            Gizmos.color = Color.yellow;
            if(_transDataList != null && _transDataList.Count > 1)
            {
                var v3 = (_transDataList.ToArray());
                if(!UseSlider)
                {
                    DrawPathHelper(v3, Color.red, "gizmos");
                }
                else
                {
                    DrawPathHelper(v3, Color.red, SliderValue);
                }
            }

            Gizmos.color = Color.green;
            for (int i = 0; i < _transKeyframeList.Count; i += 2)
            {
                if (i + 1 >= _transKeyframeList.Count)
                    break;

                if(!_transKeyframeList[i].TransformEvent.UseCurve ||
                    _transKeyframeList[i].HasSyncTrans ||
                    _transKeyframeList[i + 1].HasSyncTrans)
                {
                    Gizmos.DrawLine(_transKeyframeList[i].TransformEvent.Position, _transKeyframeList[i+1].TransformEvent.Position);
                }
            }
        }

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

            Vector3 p = uuu * p0;
            p += 3 * uu * t * p1;
            p += 3 * u * tt * p2;
            p += ttt * p3;

            return p;
        }

        public static Vector3[] PathControlPointGenerator(Vector3[] path)
        {
            Vector3[] suppliedPath;
            Vector3[] vector3s;

            //create and store path points:
            suppliedPath = path;

            //populate calculate path;
            int offset = _offset;
            vector3s = new Vector3[suppliedPath.Length + offset];
            Array.Copy(suppliedPath, 0, vector3s, 1, suppliedPath.Length);

            //populate start and end control points:
            //vector3s[0] = vector3s[1] - vector3s[2];
            vector3s[0] = vector3s[1] + (vector3s[1] - vector3s[2]);
            vector3s[vector3s.Length - 1] = vector3s[vector3s.Length - 2] + (vector3s[vector3s.Length - 2] - vector3s[vector3s.Length - 3]);

            //is this a closed, continuous loop? yes? well then so let's make a continuous Catmull-Rom spline!
            if (vector3s[1] == vector3s[vector3s.Length - 2])
            {
                Vector3[] tmpLoopSpline = new Vector3[vector3s.Length];
                Array.Copy(vector3s, tmpLoopSpline, vector3s.Length);
                tmpLoopSpline[0] = tmpLoopSpline[tmpLoopSpline.Length - 3];
                tmpLoopSpline[tmpLoopSpline.Length - 1] = tmpLoopSpline[2];
                vector3s = new Vector3[tmpLoopSpline.Length];
                Array.Copy(tmpLoopSpline, vector3s, tmpLoopSpline.Length);
            }

            return (vector3s);
        }

        //andeeee from the Unity forum's steller Catmull-Rom class ( http://forum.unity3d.com/viewtopic.php?p=218400#218400 ):
        public Vector3 Interp(Vector3[] pts, float t)
        {
            int numSections = pts.Length - 3;
            int currPt = Mathf.Min(Mathf.FloorToInt(t * (float)numSections), numSections - 1);
            float u = t * (float)numSections - (float)currPt;

            Vector3 a = pts[currPt];
            Vector3 b = pts[currPt + 1];
            Vector3 c = pts[currPt + 2];
            Vector3 d = pts[currPt + 3];

            return .5f * (
                (-a + 3f * b - 3f * c + d) * (u * u * u)
                + (2f * a - 5f * b + 4f * c - d) * (u * u)
                + (-a + c) * u
                + 2f * b
            );
        }

        private void DrawPathHelper(Vector3[] path, Color color, string method)
        {
            Vector3[] vector3s = PathControlPointGenerator(path);

            //Line Draw:
            Vector3 prevPt = Interp(vector3s, 0);
            int SmoothAmount = path.Length * _rate;
            for (int i = 1; i <= SmoothAmount; i++)
            {
                float pm = (float)i / SmoothAmount;
                Vector3 currPt = Interp(vector3s, pm);

                Gizmos.color = color;
                if (method == "gizmos")
                {
                    Gizmos.DrawLine(currPt, prevPt);
                }
                else if (method == "handles")
                {
                    Debug.LogError("iTween Error: Drawing a path with Handles is temporarily disabled because of compatability issues with Unity 2.6!");
                    //UnityEditor.Handles.DrawLine(currPt, prevPt);
                }
                prevPt = currPt;
            }
        }

        private void DrawPathHelper(Vector3[] path, Color color, float t)
        {
            Vector3[] vector3s = PathControlPointGenerator(path);

            //Line Draw:
            Vector3 prevPt = Interp(vector3s, 0);
            Gizmos.color = color;
            int SmoothAmount = path.Length * _rate;
            for (int i = 1; i <= SmoothAmount; i++)
            {
                float pm = (float)i / SmoothAmount;
                if (pm > t) return;
                Vector3 currPt = Interp(vector3s, pm);
                Gizmos.DrawLine(currPt, prevPt);
                prevPt = currPt;
            }
        }
    }
}