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


namespace MPStudio
{
    [DisallowMultipleComponent]
    [DefaultExecutionOrder(-1)]
    public class ToolManager : MonoBehaviour
    {
        public static ToolManager Inst { get; private set; }
        
        protected virtual  void Awake()
        {
            if (Inst == null)
            {
                Inst = this;
            }
            else if (Inst != this)
            {
                Destroy(gameObject);
            }
        }
        
        protected virtual void Start()
        {

           // this.TestWeight();
        }

        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
        }
    }
}