using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using MPStudioManagers;
using UnityEngine;
using UnityEngine.Events;

using static MPStudio.Note;
namespace MPStudio
{
    [DisallowMultipleComponent]
    [DefaultExecutionOrder(-1)]
    public class ToolManager : MonoBehaviour
    {
        public float LogRecordCD = 7f;
        public static ToolManager Inst { get; private set; }

        private string lineChar = "";
        
        //日志系统可以记录10个小时的生命周期，因为10个小时是不同天数玩玩的。还有概率游戏需要大量记录才能缺点是否走了分支
        protected virtual  void Awake()
        {
            if (Inst == null)
            {
                Inst = this;
            }
            else if (Inst != this)
            {
                Destroy(gameObject);
            }
        }
        
        protected virtual void Start()
        {
            lineChar = GetLineChar();
           // this.TestWeight();
           InitLogFile();
        }

        private void InitLogFile()
        {
            
            //Debug("a");
            //pInfo("a");
            //pWarning("a");
            //pError("a");
            Note.pprint("init log file");
            IfCreateLogFile();
            OverDelete();
            
            StartRecord();
        }

        private void OnApplicationQuit()
        {
            //没有保存的记录清空，但是真机上不清空
            #if UNITY_EDITOR
            Note.LogMsg.Clear();
            #endif
        }

        private void IfCreateLogFile()
        {
            ToolCollect.CreateText(Path.Combine(Application.persistentDataPath,"gLog.txt"),"game init"+lineChar);
        }

        private void OverDelete()
        {
     
            string content = ToolCollect.ReadText(Path.Combine(Application.persistentDataPath, "gLog.txt"));
             var data =content.Split(new[] { lineChar }, StringSplitOptions.None);
             if (data.Length > 36000)//36万是100个小时平均1秒的时长，装下要72兆内存可能闪退，说明没有bug，改成3万6怕闪退
             {
                 Debug.Log("行数超过，当前行:"+data.Length);
                 File.Delete(Path.Combine(Application.persistentDataPath, "gLog.txt"));
                 IfCreateLogFile();
             }
            
        }

        public void AppendLog()
        {
            //pCritical("sskk");
            //UnityEngine. Debug.Log("追加一次数据");
            StringBuilder sb =new StringBuilder();
            var data = new List<string>( Note.LogMsg);
            Note.LogMsg.Clear();

            for (int i = 0; i < data.Count; i++)
            {
                sb.Append($"{data[i]}{lineChar}");
            }
            ToolCollect.AddText(Path.Combine(Application.persistentDataPath,"gLog.txt"),sb.ToString());
        }

        public void StartRecord()
        {
            
            InvokeRepeating("AppendLog",LogRecordCD,LogRecordCD);
        }

        public string GetLineChar()
        {
            return  Environment.NewLine;
            
        }

        private float timer = 0f;
        private void Update()
        {
            return;
            timer+=Time.deltaTime;
            if (timer >= 1)
            {
                Note.pprint(Time.time);
                timer = 0;
            }
          
        }


        void TestWeight()
        {
            Weight<string> w = new Weight<string>(new List<int>() { 1, 1, 2 }, new List<string>() { "a", "b", "c" });

            for (int i = 0; i < 100; i++)
            {
                print(w.GetRandomItem());
            }
        }

        void testFunc()
        {
            ToolManager.Delay(this,2f, () =>
            {
                print(Time.time);
                
            });
        }
        
        public static void Delay(MonoBehaviour mono, float second, UnityAction action)
        {
            IEnumerator delay()
            {
                yield return new WaitForSeconds(second);
                action?.Invoke();
            }

            mono.StartCoroutine(delay());
        }

        public static T Find<T>(Transform PP, string targetName) where T : Component
        {
            Transform FindTrans(Transform aParent, string aName)
            {
                foreach (Transform child in aParent)
                {
                    if (child.name == aName) return child;

                    //遇到有GameObject就不要找了，避免子mono冗余
                    if (child.name.Contains("GameObject") && (child.name.StartsWith("GameObject") == false))
                    {
                    }
                    else
                    {
                        var result = FindTrans(child, aName);
                        if (result != null) return result;
                    }
                }

                return null;
            }

            var t = FindTrans(PP, targetName);
            if (t != null)
            {
                T res = t.GetComponent<T>();
                if (res != null)
                {
                    
                    return res;
                }
                else
                {
                    //Debug.Log("Error: trans's comp don't find");
                    return null;
                }
            }
            else
            {
                //Debug.Log("Error: trans don't find");
                return default;
            }
            
        }
        
        public static T FindComponent<T>(MonoBehaviour mono, string targetName) where T : Component
        {
            Transform FindTrans(Transform aParent, string aName)
            {
                foreach (Transform child in aParent)
                {
                    if (child.name == aName) return child;

                    if (child.name.Contains("GameObject") && (child.name.StartsWith("GameObject") == false))
                    {
                    }
                    else
                    {
                        var result = FindTrans(child, aName);
                        if (result != null) return result;
                    }
                }

                return null;
            }

            var t = FindTrans(mono.transform, targetName);
            return t != null ? t.GetComponent<T>() : default;
        }
        
        
        
        public static Transform[] GetChildArray(Transform t)
        {
            var res = new Transform[t.childCount];

            for (var i = 0; i < res.Length; i++) res[i] = t.GetChild(i);

            return res;
        }

        public static Transform LocalReset(Transform t)
        {
            t.localPosition = Vector3.zero;
            t.localRotation = Quaternion.identity;
            t.localScale = Vector3.one;
            return t;
        }
        
        public static RectTransform SetWidth(RectTransform rect, float x)
        {
            var sizeDelta = rect.sizeDelta;
            sizeDelta = new Vector2(x, sizeDelta.y);
            rect.sizeDelta = sizeDelta;
            return rect;
        }

        public static RectTransform SetHeight(RectTransform rect, float y)
        {
            var sizeDelta = rect.sizeDelta;
            sizeDelta = new Vector2(sizeDelta.x, y);
            rect.sizeDelta = sizeDelta;
            return rect;
        }

        public static RectTransform SetPosX(RectTransform rect, float val)
        {
            var anchoredPosition3D = rect.anchoredPosition3D;
            anchoredPosition3D = new Vector3(val, anchoredPosition3D.y, anchoredPosition3D.z);
            rect.anchoredPosition3D = anchoredPosition3D;
            return rect;
        }

        public static RectTransform SetPosY(RectTransform rect, float val)
        {
            var anchoredPosition3D = rect.anchoredPosition3D;
            anchoredPosition3D = new Vector3(anchoredPosition3D.x, val, anchoredPosition3D.z);
            rect.anchoredPosition3D = anchoredPosition3D;
            return rect;
        }
        
        
        
        public static Vector3 GetCursorPos()
        {
            var cursorPos = Camera.main.ScreenToWorldPoint(new Vector3(
                Input.mousePosition.x,
                Input.mousePosition.y,
                -Camera.main.transform.position.z
            ));
            return cursorPos;
        }

        
        
        public static Vector2 WorldToCanvasPos(Canvas canvas, Vector3 world)
        {
            RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform,
                world, canvas.GetComponent<Camera>(), out var pos);
            return pos;
        }
        
        
        
        public void LookAtTarget(Vector3 targetPos)
        {
            Vector2 direction = targetPos - transform.position;
            float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg - 90;
            transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
        }
        
        
        
        // 通用震动接口
        public void Vibrate(float leftMotor = 0f, float rightMotor = 0f, float duration = 0.1f)
        {
#if UNITY_ANDROID || UNITY_IOS
        Handheld.Vibrate(); // 手机震动（短震动）
#elif UNITY_STANDALONE_WIN || UNITY_EDITOR
           // Input.SetJoystickVibration(0, leftMotor, rightMotor); // 手柄震动
            Invoke(nameof(StopVibration), duration);
#endif
        }

        void StopVibration()
        {
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
           // Input.SetJoystickVibration(0, 0f, 0f);
#endif
        }
        
        
        public static T AddOrGetComponent<T>( GameObject go) where T : Component
        {
            var temp = go.GetComponent<T>();

            if (temp == null) temp = go.AddComponent<T>();

            return temp;
        }
    }
}