using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public static class EffectMgr
{
    public static float TimeSpeed = 1;

    private static WaitForEndOfFrame WaitForNextFrame = new WaitForEndOfFrame();
    //逐渐显示(Image)
    public static Coroutine GraduallyAppear(this Image picture, float duration, UnityAction<Image> callback = null)
    {
        return MonoMgr.Getinstance().StartCoroutine(IEGraduallyAppear(picture, duration, callback));
    }
    private static IEnumerator IEGraduallyAppear(Image picture, float duration, UnityAction<Image> callback = null)
    {
        Color color = picture.color;

        float ColorPercent = 1 - color.a;

        while (color.a < 1)
        {
            color.a += Time.deltaTime / duration * ColorPercent;
            picture.color = color;
            yield return WaitForNextFrame;
        }
        callback?.Invoke(picture);
    }

    //逐渐显示(Text)
    public static Coroutine GraduallyAppear(this Text picture, float duration, UnityAction<Text> callback = null)
    {
        return MonoMgr.Getinstance().StartCoroutine(IEGraduallyAppear(picture, duration, callback));
    }
    private static IEnumerator IEGraduallyAppear(Text picture, float duration, UnityAction<Text> callback = null)
    {
        Color color = picture.color;

        float ColorPercent = 1 - color.a;

        while (color.a < 1)
        {
            color.a += Time.deltaTime / duration * ColorPercent;
            picture.color = color;
            yield return WaitForNextFrame;
        }
        callback?.Invoke(picture);
    }

    //逐渐消失(Image)
    public static Coroutine GraduallyDisappear(this Image picture, float duration, UnityAction<Image> callback = null)
    {
        return MonoMgr.Getinstance().StartCoroutine(IEGraduallyDisappear(picture, duration, callback));
    }
    private static IEnumerator IEGraduallyDisappear(Image picture, float duration, UnityAction<Image> callback = null)
    {
        Color color = picture.color;

        float Percent = color.a;

        while (color.a > 0)
        {
            color.a -= Time.deltaTime / duration;
            picture.color = color;
            yield return WaitForNextFrame;
        }
        callback?.Invoke(picture);
    }

    //逐渐消失(Text)
    public static Coroutine GraduallyDisappear(this Text picture, float duration, UnityAction<Text> callback = null)
    {
        return MonoMgr.Getinstance().StartCoroutine(IEGraduallyDisappear(picture, duration, callback));
    }
    private static IEnumerator IEGraduallyDisappear(Text picture, float duration, UnityAction<Text> callback = null)
    {
        Color color = picture.color;

        float Percent = color.a;

        while (color.a > 0)
        {
            color.a -= Time.deltaTime / duration;
            picture.color = color;
            yield return WaitForNextFrame;
        }
        callback?.Invoke(picture);
    }

    //消失复现循环(Image)
    public static Coroutine GraduallyAppearAndDisAppear(this Image picture)
    {
        return MonoMgr.Getinstance().StartCoroutine(IEGraduallyAppearAndDisAppear(picture));
    }
    private static IEnumerator IEGraduallyAppearAndDisAppear(Image picture)
    {
        Color color = picture.color;
        while (true)
        {
            while (color.a > 0)
            {
                color.a -= Time.deltaTime;
                picture.color = color;
                yield return WaitForNextFrame;
            }
            while (color.a < 1)
            {
                color.a += Time.deltaTime;
                picture.color = color;
                yield return WaitForNextFrame;
            }
        }
    }

    //消失复现循环(Text)
    public static Coroutine GraduallyAppearAndDisAppear(this Text picture)
    {
        return MonoMgr.Getinstance().StartCoroutine(IEGraduallyAppearAndDisAppear(picture));
    }
    private static IEnumerator IEGraduallyAppearAndDisAppear(Text picture)
    {
        Color color = picture.color;
        while (true)
        {
            while (color.a > 0)
            {
                color.a -= Time.deltaTime;
                picture.color = color;
                yield return WaitForNextFrame;
            }
            while (color.a < 1)
            {
                color.a += Time.deltaTime;
                picture.color = color;
                yield return WaitForNextFrame;
            }
        }
    }

    //放大缩小
    public static Coroutine GraduallyChangeScale(this Transform picture, Vector2 endScale, float duration, UnityAction<Transform> func = null)
    {
        return MonoMgr.Getinstance().StartCoroutine(IEGraduallyChangeScale(picture, endScale, duration, func));
    }
    private static IEnumerator IEGraduallyChangeScale(Transform picture, Vector2 endScale, float duration, UnityAction<Transform> func = null)
    {
        Vector2 originScale = picture.localScale;

        Vector2 nowScale = picture.localScale;

        int para = endScale.x > originScale.x ? 1 : -1;

        while (nowScale.x < endScale.x * para)
        {
            nowScale += Time.deltaTime * (endScale - originScale) / duration;

            picture.localScale = nowScale;

            yield return WaitForNextFrame;
        }

        picture.GetComponent<RectTransform>().localScale = endScale;

        func?.Invoke(picture);
    }


    //旋转 参数：图片，转几圈，最后角度，是否顺时针，持续时间，回调函数
    public static Coroutine GraduallyRotate(this Transform picture, int Rotatetimes, float lastangel, bool clockwise, float duration, UnityAction<Transform> callback = null)
    {
        return MonoMgr.Getinstance().StartCoroutine(IEGraduallyRotate(picture, Rotatetimes, lastangel, clockwise, duration, callback));
    }
    private static IEnumerator IEGraduallyRotate(Transform picture, int Rotatetimes, float lastangel, bool clockwise, float duration, UnityAction<Transform> callback = null)
    {
        Vector3 OriginRotate = picture.localEulerAngles;

        Vector3 NowRotate = picture.localEulerAngles;

        float nowangel = picture.eulerAngles.z % 360;


        if (nowangel < 0)
        {
            nowangel = 360 + nowangel;
        }

        lastangel %= 360;
        if (lastangel < 0)
        {
            lastangel = 360 + lastangel;
        }

        float totalangle;

        float Goingangle = 0;

        //是否顺时针
        if (clockwise)
        {
            float angel = nowangel - lastangel;

            if (angel < 0)
            {
                angel = 360 + angel;
            }

            totalangle = angel + Rotatetimes * 360;

            while (Goingangle < totalangle)
            {

                float steprotate = Time.deltaTime * (totalangle - OriginRotate.z) / duration;

                NowRotate.z -= steprotate;

                picture.localEulerAngles = NowRotate;

                Goingangle += steprotate;

                yield return WaitForNextFrame;
            }

            OriginRotate.z = lastangel;

            picture.localEulerAngles = OriginRotate;
        }
        else
        {
            float angel = lastangel - nowangel;

            if (angel < 0)
            {
                angel = 360 + angel;
            }

            totalangle = angel + Rotatetimes * 360;

            while (Goingangle < totalangle)
            {
                float steprotate = Time.deltaTime * (totalangle - OriginRotate.z) / duration;

                NowRotate.z += steprotate;

                picture.localEulerAngles = NowRotate;

                Goingangle += steprotate;

                yield return WaitForNextFrame;
            }

            OriginRotate.z = lastangel;

            picture.localEulerAngles = OriginRotate;
        }

        callback?.Invoke(picture);
    }

    //移动
    public static Coroutine DoMove(this RectTransform picture, float duration, Vector2 endpos, UnityAction<RectTransform> callback = null)
    {
        return MonoMgr.Getinstance().StartCoroutine(IEDoMove(picture, duration, endpos, callback));
    }
    private static IEnumerator IEDoMove(RectTransform picture, float duration, Vector2 endpos, UnityAction<RectTransform> callback = null)
    {
        Vector2 startpos = picture.anchoredPosition;

        Vector2 nowpos = picture.anchoredPosition;

        Vector2 Dir = (endpos - startpos).normalized;

        Vector2 GoingDir = (endpos - nowpos).normalized;

        while (Dir.x * GoingDir.x > 0 || Dir.y * GoingDir.y > 0)
        {
            nowpos += Time.deltaTime * (endpos - startpos) / duration;

            picture.anchoredPosition = nowpos;

            GoingDir = (endpos - nowpos).normalized;

            yield return WaitForNextFrame;
        }

        picture.anchoredPosition = endpos;

        callback?.Invoke(picture);
    }

    //打字机效果
    public static Coroutine TyperEffect(this Text text, string conststring, string totalstring, float intervaltime = 0.05f, UnityAction<Text> callback = null)
    {
        return MonoMgr.Getinstance().StartCoroutine(IETyperEffect(text, conststring, totalstring, intervaltime, callback));
    }

    private static IEnumerator IETyperEffect(Text text, string conststring, string totalstring, float intervaltime, UnityAction<Text> callback = null)
    {
        string str = totalstring.Substring(conststring.Length);
        text.text = conststring;
        int index = 0;
        while (index < str.Length)
        {
            text.text += str[index];
            index++;
            yield return new WaitForSeconds(intervaltime);
        }
        callback?.Invoke(text);
    }

    //延迟函数
    public static Coroutine Invoke<T>(this object obj, float time, T parm, UnityAction<T> func)
    {
        return MonoMgr.Getinstance().StartCoroutine(IEInvoke(time, parm, func));
    }
    private static IEnumerator IEInvoke<T>(float time, T parm, UnityAction<T> func)
    {
        yield return new WaitForSeconds(time);
        func.Invoke(parm);
    }

    public static Coroutine Invoke(this object obj, float time, UnityAction func)
    {
        return MonoMgr.Getinstance().StartCoroutine(IEInvoke(time, func));
    }
    private static IEnumerator IEInvoke(float time, UnityAction func)
    {
        yield return new WaitForSeconds(time);
        func.Invoke();
    }

    //设置为透明方法
    public static void HideImage(this Image picture)
    {
        Color color = picture.color;
        color.a = 0;
        picture.color = color;
    }

    //恢复透明度方法
    public static void ShowImage(this Image picture)
    {
        Color color = picture.color;
        color.a = 1;
        picture.color = color;
    }

    //初始化
    public static void ReSet(this Transform trans)
    {
        trans.localPosition = Vector3.zero;
        trans.localScale = Vector3.one;

        RectTransform rect = null;
        trans.TryGetComponent(out rect);

        if (rect != null)
        {
            rect.anchoredPosition = Vector3.zero;
        }

    }

    public static void ReSet(this Transform trans, Vector3 pos)
    {
        trans.localPosition = pos;
        trans.localScale = Vector3.one;

        RectTransform rect = null;
        trans.TryGetComponent(out rect);

        if (rect != null)
        {
            rect.anchoredPosition = pos;
        }

    }

    public static void ReSet(this Transform trans, Vector3 pos, Vector3 Scale)
    {
        trans.localPosition = pos;
        trans.localScale = Scale;

        RectTransform rect = null;
        trans.TryGetComponent(out rect);

        if (rect != null)
        {
            rect.anchoredPosition = pos;
        }
    }

    public static void ReSet(this Transform trans, Vector2 Offsetmin, Vector2 Offsetmax, Vector3 pos, Vector3 Scale)
    {
        RectTransform rect = null;
        trans.TryGetComponent(out rect);

        if (rect != null)
        {
            rect.offsetMin = Offsetmin;
            rect.offsetMax = Offsetmax;
            rect.anchoredPosition = pos;
            rect.localScale = Scale;
        }
    }

    public static void ResetToCanvas(this Transform trans, E_Layer layer)
    {
        try
        {
            switch (layer)
            {
                case E_Layer.bot:
                    trans.SetParent(UIMgr.Getinstance().bot);
                    break;
                case E_Layer.lower_mid:
                    trans.SetParent(UIMgr.Getinstance().lower_mid);
                    break;
                case E_Layer.mid:
                    trans.SetParent(UIMgr.Getinstance().mid);
                    break;
                case E_Layer.upper_mid:
                    trans.SetParent(UIMgr.Getinstance().upper_mid);
                    break;
                case E_Layer.lower_top:
                    trans.SetParent(UIMgr.Getinstance().lower_top);
                    break;
                case E_Layer.top:
                    trans.SetParent(UIMgr.Getinstance().top);
                    break;
                case E_Layer.upper_top:
                    trans.SetParent(UIMgr.Getinstance().upper_top);
                    break;
                case E_Layer.system:
                    trans.SetParent(UIMgr.Getinstance().system);
                    break;
            }
            trans.ReSet();
        }
        catch
        {
            Debug.Log("ResetToCanvas失败");
        }
    }

    public static void ResetToCanvas(this Transform trans, E_Layer layer, Vector3 pos)
    {
        try
        {
            switch (layer)
            {
                case E_Layer.bot:
                    trans.SetParent(UIMgr.Getinstance().bot);
                    break;
                case E_Layer.lower_mid:
                    trans.SetParent(UIMgr.Getinstance().lower_mid);
                    break;
                case E_Layer.mid:
                    trans.SetParent(UIMgr.Getinstance().mid);
                    break;
                case E_Layer.upper_mid:
                    trans.SetParent(UIMgr.Getinstance().upper_mid);
                    break;
                case E_Layer.lower_top:
                    trans.SetParent(UIMgr.Getinstance().lower_top);
                    break;
                case E_Layer.top:
                    trans.SetParent(UIMgr.Getinstance().top);
                    break;
                case E_Layer.upper_top:
                    trans.SetParent(UIMgr.Getinstance().upper_top);
                    break;
                case E_Layer.system:
                    trans.SetParent(UIMgr.Getinstance().system);
                    break;
            }
            trans.ReSet(pos);
        }
        catch
        {
            Debug.Log("ResetToCanvas失败");
        }
    }

    public static void ResetToCanvas(this Transform trans, E_Layer layer, Vector3 pos, Vector3 Scale)
    {
        try
        {
            switch (layer)
            {
                case E_Layer.bot:
                    trans.SetParent(UIMgr.Getinstance().bot);
                    break;
                case E_Layer.lower_mid:
                    trans.SetParent(UIMgr.Getinstance().lower_mid);
                    break;
                case E_Layer.mid:
                    trans.SetParent(UIMgr.Getinstance().mid);
                    break;
                case E_Layer.upper_mid:
                    trans.SetParent(UIMgr.Getinstance().upper_mid);
                    break;
                case E_Layer.lower_top:
                    trans.SetParent(UIMgr.Getinstance().lower_top);
                    break;
                case E_Layer.top:
                    trans.SetParent(UIMgr.Getinstance().top);
                    break;
                case E_Layer.upper_top:
                    trans.SetParent(UIMgr.Getinstance().upper_top);
                    break;
                case E_Layer.system:
                    trans.SetParent(UIMgr.Getinstance().system);
                    break;
            }
            trans.ReSet(pos, Scale);
        }
        catch
        {
            Debug.Log("ResetToCanvas失败");
        }
    }

    public static void ResetToCanvas(this Transform trans, Transform parent)
    {
        trans.SetParent(parent);

        trans.ReSet();
    }

    public static void ResetToCanvas(this Transform trans, Transform parent, Vector3 pos)
    {
        trans.SetParent(parent);

        trans.ReSet(pos);
    }

    public static void ResetToCanvas(this Transform trans, Transform parent, Vector3 pos, Vector3 Scale)
    {
        trans.SetParent(parent);

        trans.ReSet(pos, Scale);
    }

    public static void ResetToCanvas(this Transform trans, Transform parent, Vector2 Offsetmin, Vector2 Offsetmax, Vector3 pos, Vector3 Scale)
    {
        trans.SetParent(parent);

        trans.ReSet(pos, Scale);
    }

    public static void AnchorframeResetToCanvas(this Transform trans, Transform parent)
    {
        trans.transform.SetParent(parent);

        trans.transform.localScale = Vector3.one;

        trans.transform.localPosition = Vector3.zero;

        (trans.transform as RectTransform).offsetMax = Vector3.zero;
        (trans.transform as RectTransform).offsetMin = Vector3.zero;
    }
}