using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XRTool.Util;
using SC.XR.Unity.Module_InputSystem;
using System;
using System.Linq;
using ShadowStudio.Model;
using UnityEngine.EventSystems;
using TriLib.Extras;

namespace ShadowStudio.Tool
{
    /// <summary>
    /// 画笔功能
    /// </summary>
    public class DrawPener : UnitySingleton<DrawPener>
    {
        /// <summary>
        /// 笔的材质
        /// </summary>
        public Material penMate;
        /// <summary>
        /// 笔颜色的名称
        /// </summary>
        public string colorName;
        /// <summary>
        /// 最小间距
        /// </summary>
        public float minDis = 0.01f;
        /// <summary>
        /// 默认笔头的粗细
        /// </summary>
        public float radius = 0.005f;
        /// <summary>
        /// 笔的颜色
        /// </summary>
        public Color penColor = Color.white;
        /// <summary>
        /// 线的预制体
        /// </summary>
        public LineSegment linePrefab;
        /// <summary>
        /// 每根线段最多100点
        /// </summary>
        public int maxPointOfLine = 100;
        /// <summary>
        /// 所有线段加起来最多500个点
        /// </summary>
        public int maxPointOfSegment = 500;
        /// <summary>
        /// 有可能要撤销对应的组件
        /// </summary>
        private Queue<LineSegment> lines;
        private LineSegment currentLine;
        private Coroutine drawCoroutine;
        private InputDevicePartBase part;
        private Vector3 lastPosition = Vector3.zero;
        public string defaultShader = "Mixed Reality Toolkit/Standard";
        private int currentPoint;
        /// <summary>
        /// 资源的id
        /// </summary>
        public static string artLineId = "ArtId_GameObject";
        /// <summary>
        /// 线与对应的名字的集合
        /// </summary>
        private Dictionary<string, LineSegment> lineMap;
        /// <summary>
        /// 请他用户的线段id
        /// 仅房主使用此数据
        /// </summary>
        private List<int> otherUserList;
        private List<int> userList;
        private DrawPlaneContainer drawPlane;

        public List<int> OtherUserList
        {
            get
            {
                if (otherUserList == null)
                {
                    otherUserList = new List<int>();
                }
                return otherUserList;
            }
        }
        public List<int> UserList
        {
            get
            {
                if (userList == null)
                {
                    userList = new List<int>();
                }
                return userList;
            }
        }

        public LineSegment GetLine(string lineName)
        {
            if (lineMap != null && lineMap.ContainsKey(lineName))
            {
                return lineMap[lineName];
            }
            return null;
        }
        protected override void Awake()
        {
            base.Awake();
            DisActiveDrawPen();
        }
        public void ActiveDrawPen()
        {
            gameObject.SetActive(true);
        }
        /// <summary>
        /// 添加老线
        /// </summary>
        /// <param name="line"></param>
        public void AddOldLine(LineSegment line)
        {
            if (line)
            {
                if (lineMap == null)
                {
                    lineMap = new Dictionary<string, LineSegment>();
                }
                if (!lineMap.ContainsKey(line.name))
                {
                    lineMap.Add(line.name, line);
                }
                if (lines == null)
                {
                    lines = new Queue<LineSegment>();
                }
                if (line.Line.positionCount > 0 && !lines.Contains(line))
                {
                    currentPoint += line.Line.positionCount;
                    lines.Enqueue(line);
                }
            }
        }

        public void DisActiveDrawPen()
        {
            gameObject.SetActive(false);
        }
        public void OnEnable()
        {
            DispatcherBase.KeyDownDelegateRegister(OnKeyDownAction);
            DispatcherBase.KeyUpDelegateRegister(OnKeyUpAction);
            //caoting 2021/6/11 合并新的sdk
            if (SCInputModule.Instance)
            {
                SCInputModule.Instance.CanDrag = false;
            }
        }



        private void OnDisable()
        {
            DispatcherBase.KeyDownDelegateUnRegister(OnKeyDownAction);
            DispatcherBase.KeyUpDelegateUnRegister(OnKeyUpAction);
            //caoting 2021/6/11 合并新的sdk
            if (SCInputModule.Instance)
            {
                SCInputModule.Instance.CanDrag = true;
            }
        }
        /// <summary>
        /// 抬起按钮时
        /// </summary>
        /// <param name="keyCode"></param>
        /// <param name="part"></param>
        private void OnKeyUpAction(InputKeyCode keyCode, InputDevicePartBase part)
        {
            drawPlane = null;
            lastPosition = Vector3.zero;
            ClearPen();
            isHandlerobj = false;
            distance = 0;
            isNoCheck = false;
        }

        public void ClearPen()
        {
            if (drawCoroutine != null)
            {
                StopCoroutine(drawCoroutine);
            }
            drawCoroutine = null;
            if (lines == null)
            {
                lines = new Queue<LineSegment>();
            }
            if (currentLine)
            {
                if (currentLine.Line.positionCount > 1)
                {
                    if (!lines.Contains(currentLine))
                    {
                        currentLine.StopSyn();
                        lines.Enqueue(currentLine);
                    }
                }
                else
                {
                    Destroy(currentLine.gameObject);
                }
            }
            currentLine = null;
        }

        private bool isHandlerobj;
        private bool isNoCheck;
        private float distance;
        /// <summary>
        /// 按下按钮时
        /// </summary>
        /// <param name="keyCode"></param>
        /// <param name="part"></param>
        private void OnKeyDownAction(InputKeyCode keyCode, InputDevicePartBase part)
        {
            if (lines == null)
            {
                lines = new Queue<LineSegment>();
            }
            ///当前的还存在上一个画笔
            if (currentLine || drawCoroutine != null || this.part != part)
            {
                ClearPen();
            }
            ///当大于线段时,清除掉相关的线段
            while (currentPoint >= maxPointOfSegment - maxPointOfLine)
            {
                ClearOldLine();
            }
            this.part = part;
            var tmp = part.inputDataBase.SCPointEventData.pointerCurrentRaycast.gameObject;
            if (tmp)
            {
                ///如果点击了某个UI按钮,触发对应的点击事件,不绘制图形
                var tmpbutton = tmp.GetComponentInParent<IPointerClickHandler>();
                if (tmpbutton != null)
                {
                    if (!isNoCheck)
                    {
                        isHandlerobj = true;
                        if (isHandlerobj)
                        {
                            if (distance == 0)
                            {
                                distance = GetDis();
                            }
                        }
                    }
                    //tmpbutto n.OnPointerClick(part.inputDataBase.SCPointEventData);
                    //return;
                }
                var downHandler = tmp.GetComponentInParent<IPointerDownHandler>();
                if (downHandler != null)
                {
                    if (!isNoCheck)
                    {
                        isHandlerobj = true;
                        if (isHandlerobj)
                        {
                            if (distance == 0)
                            {
                                distance = GetDis();
                            }
                        }
                    }
                    //downHandler.OnPointerDown(part.inputDataBase.SCPointEventData);
                    //return;
                }
                ///在画板上绘制
                else if (drawPlane = tmp.GetComponentInParent<DrawPlaneContainer>())
                {

                }
                else
                {
                    drawPlane = null;
                }
            }
            drawCoroutine = StartCoroutine(DrawLine(keyCode));
        }
        private float helpAngle = 1f;
        /// <summary>
        /// 画线功能的实现
        /// 如果画在画线板上时,不计入总点数
        /// </summary>
        /// <param name="keyCode"></param>
        /// <returns></returns>
        private IEnumerator DrawLine(InputKeyCode keyCode)
        {
            var obj = part.inputDataBase.SCPointEventData.pointerCurrentRaycast.gameObject;
            currentLine = CreateLine();
            currentLine.IsSingleLine = !drawPlane;
            if (lineMap == null)
            {
                lineMap = new Dictionary<string, LineSegment>();
            }
            if (!lineMap.ContainsKey(currentLine.name))
            {
                lineMap.Add(currentLine.name, currentLine);
            }

            yield return currentLine;
            Vector3 pointPos = part.detectorBase.pointerBase.cursorBase.transform.position;
            //Vector3 pointPos = part.pointerBase.cursorBase.transform.position;
            if (API_Module_InputSystem.InputDeviceStatus(InputDeviceType.KS))
            {
              //  pointPos = API_Module_InputSystem_KS.KSPosition(API_Module_InputSystem_KS.GCType.Right);
              //  pointPos += API_Module_InputSystem_KS.KSTransform(API_Module_InputSystem_KS.GCType.Right).forward.normalized * SystemSettingMgr.Instance.settings.RayDis;
            }


            if (lastPosition != Vector3.zero)
            {
                GameNode.Instance.SetParent(ObjNode.World, currentLine.transform,
                GameNode.Instance.LocalPosition(ObjNode.World, lastPosition, 1), Vector3.zero, Vector3.one, true);
                currentLine.AddPosition(lastPosition);
                currentPoint++;
            }
            else
            {
                GameNode.Instance.SetParent(ObjNode.World, currentLine.transform,
                    GameNode.Instance.LocalPosition(ObjNode.World, pointPos, 1), Vector3.zero, Vector3.one, true);
            }
            while (currentLine && part)
            {
                //if (obj != part.inputDataBase.SCPointEventData.pointerCurrentRaycast.gameObject)
                //{
                //    OnKeyUpAction(keyCode, part);
                //    yield break;
                //}
                Vector3 posks = part.detectorBase.pointerBase.cursorBase.transform.position;
                if (API_Module_InputSystem.InputDeviceStatus(InputDeviceType.KS))
                {
                  //  posks = API_Module_InputSystem_KS.KSPosition(API_Module_InputSystem_KS.GCType.Right);
                  //  posks += API_Module_InputSystem_KS.KSTransform(API_Module_InputSystem_KS.GCType.Right).forward.normalized * SystemSettingMgr.Instance.settings.RayDis;
                }
                if (currentLine.Line.positionCount < 1 || Vector3.Distance(posks, pointPos) >= (obj ? (minDis / 5f) : minDis))
                {
                    bool addPoint = true;
                    if (currentLine.Line.positionCount > 1)
                    {
                        Vector3 lastDir = currentLine.transform.TransformPoint(currentLine.Line.GetPosition(currentLine.Line.positionCount - 1)) -
                            currentLine.transform.TransformPoint(currentLine.Line.GetPosition(currentLine.Line.positionCount - 2));
                        Vector3 curDir = posks -
                            currentLine.transform.TransformPoint(currentLine.Line.GetPosition(currentLine.Line.positionCount - 1));
                        if (Vector3.Angle(lastDir, curDir) < helpAngle)
                        {
                            UnityLog.Instance.Log(Vector3.Angle(lastDir, curDir), 4);
                            addPoint = false;
                            if (isHandlerobj)
                            {
                                pointPos = GameSession.Instance.GetHeadForwadPos(distance, false);
                                currentLine.SetPosition(pointPos);
                            }
                            else
                            {
                                currentLine.SetPosition(posks);
                            }
                        }
                    }
                    if (addPoint)
                    {
                        if (isHandlerobj)
                        {
                            pointPos = GameSession.Instance.GetHeadForwadPos(distance, false);
                        }
                        else
                        {
                            pointPos = posks;
                        }
                        currentLine.AddPosition(pointPos);
                        currentPoint++;
                    }
                }
                if (currentLine.Line.positionCount >= maxPointOfLine)
                {
                    lastPosition = pointPos;
                    isNoCheck = true;
                    OnKeyDownAction(keyCode, part);
                    yield break;
                }
                yield return new WaitForFixedUpdate();

                //part.inputDataBase.SCPointEventData.pointerCurrentRaycast.gameObject;
                //part.pointerBase.cursorBase.transform.position;
            }
        }
        /// <summary>
        /// 创建线段
        /// </summary>
        /// <returns></returns>
        public LineSegment CreateLine()
        {
            LineSegment line;
            var lineName = UnityEngine.Random.Range(100000000, 999999999).ToString(); // DateTime.Now.ToString("MMddHHmmssf");

            if (linePrefab)
            {
                line = Instantiate(linePrefab);
                line.name = lineName;
            }
            else
            {
                GameObject obj = new GameObject(lineName, typeof(LineRenderer));
                line = obj.AddComponent<LineSegment>();
                //if (!line.Line.sharedMaterial)
                //{
                //    line.Line.sharedMaterial = penMate;
                //}
            }
            if (line)
            {
                ///如果设置了默认的材质,则使用默认材质
                if (penMate)
                {
                    line.SetLine(penMate);
                }
                line.SetLine(penColor, radius, colorName);
            }
            line.Line.positionCount = 0;
            line.Line.useWorldSpace = false;
            ///如果存在物体,则改变对齐模式,使线段看起来平整圆滑
            if (part != null && part.inputDataBase.SCPointEventData.pointerCurrentRaycast.gameObject)
            {
                line.Line.alignment = LineAlignment.TransformZ;
            }
            GameNode.Instance.SetParent(ObjNode.World, line.transform,
                    Vector3.zero, Vector3.zero, Vector3.one, true);
            return line;
        }
        /// <summary>
        /// 清除本地自己的老线段
        /// 为什么不在线发送确认清除?因为延时问题造成的不流畅问题
        /// 主动删除并释放本地内存,然后发送同步信息删除线段
        /// </summary>
        public void ClearOldLine()
        {
            ///如果此条线段尚未同步,则禁止本地删除
            if (lines.Count > 0)
            {
                var line = lines.Dequeue();
                if (line)
                {
                    currentPoint -= line.Line.positionCount;
                    lineMap.Remove(line.name);
                    ///删除线段
                    line.DelLine();
                    Destroy(line.gameObject);
                }
            }
        }
        /// <summary>
        /// 清除指定的线,删除此线段
        /// 如果此线段属于用户自己创建的,则清空对应的内存
        /// </summary>
        /// <param name="line"></param>
        public void ClearOldLine(LineSegment line)
        {
            if (line)
            {
                if (lineMap != null && lineMap.ContainsKey(line.name))
                {
                    currentPoint -= line.Line.positionCount;
                    lineMap.Remove(line.name);
                }
                Destroy(line.gameObject);
            }
        }
        /// <summary>
        /// 清除所有线段
        /// </summary>
        public void ClearAllLine(bool isClearAll = false)
        {
            if (UserList != null)
            {
                ArtInfoMgr.Instance.DelGoodsByIds(UserList);
            }
            if (isClearAll)
            {
                ClearOtherLine();
            }
        }
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        public void AddLineId(int id, bool isOther = true)
        {
            if (isOther)
            {
                OtherUserList.Add(id);
            }
            else
            {
                UserList.Add(id);
            }
        }
        /// <summary>
        /// 清空其他用户的线段
        /// </summary>
        public void ClearOtherLine()
        {
            ArtInfoMgr.Instance.DelGoodsByIds(OtherUserList);
        }

        public float GetDis()
        {
            Vector3 posks = part.detectorBase.pointerBase.cursorBase.transform.position;
            if (API_Module_InputSystem.InputDeviceStatus(InputDeviceType.KS))
            {
                posks = API_Module_InputSystem_KS.KSPosition(API_Module_InputSystem_KS.GCType.Right);
                posks += API_Module_InputSystem_KS.KSTransform(API_Module_InputSystem_KS.GCType.Right).forward.normalized * SystemSettingMgr.Instance.settings.RayDis;
            }
            float dis= Vector3.Distance(posks, GameSession.Instance.gameHead.position);
            return dis;
        }
    }
}