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

public class DisplayControllerNav : MonoBehaviour
{
    [SerializeField]
    private List<DisplayController> m_Displays = new List<DisplayController>();
    List<DisplayController> m_Stack = new List<DisplayController>();
    
    public DisplayControllerSwitchAnimation UIChangeAnimation;

    public Action<DisplayController> OnDisplayClose;

    private void Awake()
    {
        
    }


    public T LoadDisplay<T>(Action<T> onInit,bool deletePreUI) where T : DisplayController
    {
        T res = this.LoadDisplay<T>(typeof(T).Name,true, onInit, deletePreUI);
        return res;
    }
    public T LoadDisplay<T>() where T : DisplayController
    {
        T res = this.LoadDisplay<T>(typeof(T).Name, true, null,true);
        return res;
    }
    public T LoadDisplay<T>(bool showAnim) where T : DisplayController
    {
        T res = this.LoadDisplay<T>(typeof(T).Name, showAnim, null, true);
        return res;
    }

    //Dictionary<string, bool> m_DeletePreUI = new Dictionary<string, bool>();
    Dictionary<string, bool> m_PlayAnim = new Dictionary<string, bool>();

    //public float delayDeleteTime = 1f;

    /// <summary>
    /// 加载UI，先从m_Displays里找，找不到则创建
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="path"></param>
    /// <param name="displayId"></param>
    /// <returns></returns>
    public T LoadDisplay<T>(string displayId,bool showAnim,Action<T>onInit,bool DeletePreUI) where T : DisplayController
    {
        if (string.IsNullOrEmpty(displayId))
            displayId = typeof(T).Name;

        Debug.Log("toload  displayId:" + displayId);


        //m_DeletePreUI[displayId] = DeletePreUI;
        m_PlayAnim[displayId] = showAnim;

        var prePeek = GetPeek();
        if (prePeek)
        {
            //Debug.Log("prePeek.name:" + prePeek.name);
        }

        T res = FindDisplay<T>(displayId);

        if (res == null)
        {
            res = CreateDisplay<T>(displayId, onInit);
        }
        else
        {
            if (m_Stack.Contains(res))
                MoveToTop(res);//若是前面已打开的界面则移到最顶层
            else
                m_Stack.Add(res);
        }

        res.deletePreUI = DeletePreUI;

        try
        {
            if (onInit != null)
                onInit(res); //数据初始化执行最先
        }
        catch (Exception e)
        {
            GameDebug.LogError(e);
        }

/*        if (prePeek == res)
            prePeek = null;*/

        OnDCToActive(res, prePeek);

        return res;
    }

    bool animEnd = false;
    bool loadDCEnd = false;

    /// <summary>
    /// 加载新界面，释放前界面
    /// </summary>
    /// <param name="dc"></param>
    /// <param name="prePeek"></param>
    /// <param name="create"></param>
    /// <returns></returns>
    void OnDCToActive(DisplayController dc, DisplayController prePeek)
    {
        if(dc.delayDelete)
        {
            try
            {
                dc.OnDelete();
            } 
            catch (Exception e)
            {
                GameDebug.LogError(e);
            }

            dc.delayDelete = false;
        }

        //首先播放淡入动画
        if (m_PlayAnim.ContainsKey(dc.displayId) && m_PlayAnim[dc.displayId] && UIChangeAnimation != null)
        {
            try
            {
                UIChangeAnimation.ToPlayShowAnim(dc, () =>
                {
                    OnShowAnimEnd(dc, prePeek);
                });
            }
            catch (Exception e)
            {
                OnShowAnimEnd(dc, prePeek);
                GameDebug.LogError(e);
            }
        }
        else
        {
            OnShowAnimEnd(dc, prePeek);
        }
    }

    
    //淡入动画播放完,接着播放加载动画，再下一帧再WillLoadDisplay
    void OnShowAnimEnd(DisplayController dc, DisplayController prePeek)
    {
        //Debug.Log("OnShowAnimEnd dc :" + dc.name + " prePeek: " + (prePeek == null ? "" : prePeek.name));
        loadDCEnd = false;

        if ((m_PlayAnim.ContainsKey(dc.displayId) && !m_PlayAnim[dc.displayId]) || UIChangeAnimation == null)
            animEnd = true;
        else
            animEnd = false;

        //播放加载动画
        if (!animEnd)
        {
            try
            { 
                UIChangeAnimation.ToPlayInLoadingAnim(() =>
                {
                    OnPlayLoadingAnimEnd(dc, prePeek);
                });
            }
            catch (Exception e)
            {
                OnPlayLoadingAnimEnd(dc, prePeek);
                GameDebug.LogError(e);
            }
        }

        Action willLoadDisplay = delegate
        {

            if (dc.deletePreUI && prePeek != null)
            {
#if DEBUG
                Debug.Log("prePeek.WillHideDisplay() prePeek :" + (prePeek != null ? prePeek.name : ""));
#endif
                try
                {
                    prePeek.WillHideDisplay();
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                }

                OnDisplayClose?.Invoke(prePeek);
                prePeek.delayDelete = true;
            }
            
            try
            {
                Debug.Log("pwillLoadDisplay :" + (dc != null ? dc.name : ""));
                //加载数据
                dc.WillLoadDisplay();
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
            finally
            {
                OnDCWillLoadDisplayEnd(dc, prePeek);
            }
        };

        //yield return 0;

        //协程改为Invoke
        //Invoke("DoWillLoad",0.016f);
        delayAction.DelayDoAction(0.010f,willLoadDisplay);
    }
    
    private DelayAction m_DelayAction;
    public DelayAction delayAction
    {
        get
        {
            if (m_DelayAction == null)
            {
                m_DelayAction = gameObject.AddComponent<DelayAction>();
            }
            return m_DelayAction;
        }
    }

    void OnDCWillLoadDisplayEnd(DisplayController dc, DisplayController prePeek)
    {
        Debug.Log("OnDCWillLoadDisplayEnd !!  dc:" + dc.name+ "  animEnd:"+ animEnd+ "  prePeek:"+prePeek?.GetType().Name);
        //数据加载完，若加载动画播放完则播放淡出动画
        loadDCEnd = true;
        if (animEnd)
        {
            DidLoadDisplay(dc, prePeek);
        }
    }

    void OnPlayLoadingAnimEnd(DisplayController dc, DisplayController prePeek)
    {
        //Debug.Log("OnPlayLoadingAnimEnd !!  dc:" + dc.name+$"  prePeek:{prePeek}  loadDCEnd:{loadDCEnd}");
        animEnd = true;

        //加载动画播放完，若数据加载完则播放淡出动画
        if (loadDCEnd)
        {
            DidLoadDisplay(dc, prePeek);
        }
    }


    void OnDidLoadDisplayEnd(DisplayController dc, DisplayController prePeek)
    {
        if (m_PlayAnim.ContainsKey(dc.displayId) && m_PlayAnim[dc.displayId] && UIChangeAnimation != null)
        {
            try
            { 
                UIChangeAnimation.ToPlayHideAnim(
                () =>
                {
                    OnLoadDCHideAnimEnd(dc);
                });
            } 
            catch (Exception e)
            {
                Debug.LogError(e);
                OnLoadDCHideAnimEnd(dc);
            }
        }
        else
        {
            OnLoadDCHideAnimEnd(dc);
        }

    }

    /// <summary>
    /// 加载新界面的淡出动画播放完
    /// </summary>
    /// <param name="toShowDisplay"></param>
    /// <param name="toDeleteDisplay"></param>
    void OnLoadDCHideAnimEnd(DisplayController toShowDisplay)//, DisplayController toDeleteDisplay)
    {
        if (toShowDisplay != null)
            toShowDisplay.OnLoadedEndDisplay();
    }

    /// <summary>
    /// 关闭界面，唤起前界面
    /// </summary>
    /// <param name="dc"></param>
    /// <param name="nextPeek"></param>
    /// <returns></returns>
    void OnDCToDisActive(DisplayController dc,DisplayController nextPeek)
    {
        //Debug.Log("GoBackToPreDC OnDCToDisActive:" + dc.name);
        try
        {
            dc.OnDidHideDisplay(() =>
            {
                if (m_PlayAnim.ContainsKey(dc.displayId) && m_PlayAnim[dc.displayId] && UIChangeAnimation != null)
                {
                   // Debug.LogError("OnDCToDisActive  PlayHideAnim:" + dc.name);
                   try
                   {
                       UIChangeAnimation.ToPlayHideAnim(
                           () => { OnGoBackHideAnimEnd(dc); });
                   }
                   catch (Exception e)
                   {
                       OnGoBackHideAnimEnd(dc);
                       GameDebug.LogError(e);
                   }
                }
                else
                {
                    OnGoBackHideAnimEnd(dc);
                }

                //打开前界面
                if (dc .deletePreUI && nextPeek != null)
                {
                    JustActiveDC(nextPeek);
                }
            }
                );
        }
        catch (Exception e)
        {
            GameDebug.LogError(e);
            
            OnGoBackHideAnimEnd(dc);
            //打开前界面
            if (dc .deletePreUI && nextPeek != null)
            {
                JustActiveDC(nextPeek);
            }
        }
    }
    void JustActiveDC(DisplayController dc)
    {
        try
        {
            dc.WillLoadDisplay();
            
            DidLoadDisplay(dc, null);
        }
        catch (Exception e)
        {
            Debug.LogError(e);

            DidLoadDisplay(dc,null);
        }
    }

    /// <summary>
    /// WillLoadDisplay 执行完，则执行OnDidLoadDisplay
    /// </summary>
    /// <param name="dc"></param>
    void DidLoadDisplay(DisplayController dc, DisplayController prePeek)
    {
        try
        {
            //Debug.Log($"DidLoadDisplay dc:{dc.name}   prePeek:{prePeek}");

            dc.OnDidLoadDisplay(() => { OnDidLoadDisplayEnd(dc, prePeek); });

            if(prePeek)
                prePeek.OnDidHideDisplay(null);
        }
        catch (Exception e)
        {
            Debug.LogError(e);
            OnDidLoadDisplayEnd(dc, prePeek);
        }
    }

    ///// <summary>
    ///// 移到最顶层
    ///// </summary>
    ///// <param name="dc"></param>
    void MoveToTop(DisplayController dc)
    {
        var exist = m_Stack.Find(e => e == dc);
        if (exist != null)
        {
            m_Stack.Remove(exist);
            m_Stack.Add(exist);
        }
    }

    ///// <summary>
    ///// 获取最顶层UI
    ///// </summary>
    ///// <returns></returns>
    public DisplayController GetPeek()
    {
        if (m_Stack.Count == 0)
            return null;
        else
            return m_Stack[m_Stack.Count - 1];
    }
    /// <summary>
    /// 出栈
    /// </summary>
    /// <returns></returns>
    DisplayController Pop()
    {
        var peek = GetPeek();
        if (peek != null)
            m_Stack.Remove(peek);

        return peek;
    }
    /// <summary>
    /// 创建UI
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="path"></param>
    /// <param name="displayId"></param>
    /// <returns></returns>
    private T CreateDisplay<T>(string displayId, Action<T> onInit) where T : DisplayController
    {
        var go = new GameObject(typeof(T).ToString());
        T res = go.AddComponent<T>();
        res.displayId = displayId;
        res.transform.SetParent(transform);
        m_Displays.Add(res);
        m_Stack.Add(res);
        
        return res;
    }


    /// <summary>
    /// 从缓存中找
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="displayId"></param>
    /// <returns></returns>
    public T FindDisplay<T>(string displayId) where T : DisplayController
    {
        T res = m_Displays.Find(e => e.GetType().Equals(typeof(T))&& e.displayId == displayId) as T;
        return res;
    }
    public T FindDisplay<T>() where T : DisplayController
    {
        T res = m_Displays.Find(e => e.GetType().Equals(typeof(T))) as T;
        return res;
    }


	/// <summary>
    /// 从某个UI返回
    /// </summary>
    /// <param name="controller"></param>
  //  public void GoBackDisplay()
  //  {
		//if (m_Stack.Count > 1)
		//{
		//	DisplayController controller = Pop();//移出

  //      }
  //  }

    public void Remove(DisplayController dc)
    {
        if (m_Stack.Contains(dc))
        {
            m_Stack.Remove(dc);
        }
    }

    public void GoBackToPreDC()
    {
        DisplayController controller = Pop();//移出
        try
        {
            controller.WillHideDisplay();
            OnDisplayClose?.Invoke(controller);

            controller.delayDelete = true;
        }
        catch { }

        var nextPeek = GetPeek();

        OnDCToDisActive(controller, nextPeek);
    }

    /// <summary>
    /// 关闭界面的淡出动画播放完
    /// </summary>
    /// <param name="toDeleteDC"></param>
    /// <param name="delete"></param>
    void OnGoBackHideAnimEnd(DisplayController toDeleteDC)
    {
        if (toDeleteDC)
            toDeleteDC.OnDelete();

    }
    
    public void ReleaseAll()
    {
        foreach(var display in m_Displays)
        {
            if(display)
            {
                try
                {
                    display.WillHideDisplay();
                    OnDisplayClose?.Invoke(display);

                }
                catch { }

                try
                {
                    display.OnDidHideDisplay(null);
                }
                catch { }
                
                try
                {
                    display.OnDelete();
                } 
                catch { }
            }
        }
        m_Stack.Clear();
    }

    public int GetIndex(DisplayController dc)
    {
        if(m_Stack.Contains(dc))
            return m_Stack.IndexOf(dc);
        return 0;
    }

    private void OnDestroy()
    {
        if(this.UIChangeAnimation)
            Destroy(UIChangeAnimation.gameObject);
    }
}
