using System;
using System.Collections.Generic;
using Games.LogicObj;
using GCGame.Table;
using Module.Log;
using UnityEngine;
using UnityEngine.UI;
using XLua;

[Serializable]
public class LuaParamGO
{
    public string name;
    public GameObject value;
}

[LuaCallCSharp]
public class LuaUIBehaviour : MonoBehaviour
{
    internal const float GCInterval = 1; //1 second 

    internal static float lastGCTime = 0;
    public string luaScript;
    public LuaParamGO[] injectionGos;

    private bool hasAwake;

    private Action luaAwake;
    private Action luaFixedUpdate;
    private Action luaOnDestroy;
    private Action luaOnDisable;
    private Action luaOnEnable;
    private Action luaOnRevPacket;
    private Action luaStart;
    private Action luaUpdate;

    protected LuaTable scriptEnv;

    public void Awake()
    {
        if (hasAwake) return;

        hasAwake = true;

        Init();

        if (luaAwake != null) luaAwake();
    }

    private void Start()
    {
        if (luaStart != null) luaStart();
    }

    private void Update()
    {
        if (luaUpdate != null) luaUpdate();
    }

    private void FixedUpdate()
    {
        if (luaFixedUpdate != null) luaFixedUpdate();
    }

    private void OnEnable()
    {
#if UNITY_EDITOR
        // 编辑器模式下,重新打开UI,重新加载脚本,便于调试
        //Init();
        //hasAwake = true;
        //if (luaAwake != null)
        //{
        //    luaAwake();
        //}
#endif
        if (luaOnEnable != null) luaOnEnable();
    }

    private void OnDisable()
    {
        if (luaOnDisable != null) luaOnDisable();
    }

    private void OnDestroy()
    {
        if (luaOnDestroy != null) luaOnDestroy();
        luaOnDestroy = null;
        luaUpdate = null;
        luaStart = null;
        scriptEnv.Dispose();
    }

    protected virtual void Init()
    {
        if (luaScript == null)
            return;
        if (scriptEnv == null)
        {
            if (LuaMain.luaEnv == null)
            {
                Debug.LogError("LuaMain._LuaEnv == null");
                return;
            }

            scriptEnv = LuaMain.luaEnv.NewTable();
        }

        var meta = LuaMain.luaEnv.NewTable();
        meta.Set("__index", LuaMain.luaEnv.Global);
        scriptEnv.SetMetaTable(meta);
        meta.Dispose();

        scriptEnv.Set("self", gameObject);
        foreach (var injection in injectionGos) scriptEnv.Set(injection.name, injection.value);
        var script = LoadAssetBundle.Instance.LoadScriptAsset(luaScript);
        LuaMain.luaEnv.DoString(script.text, luaScript, scriptEnv);
        luaAwake = scriptEnv.GetInPath<Action>(luaScript + ".Awake");
        luaStart = scriptEnv.GetInPath<Action>(luaScript + ".Start");
        luaUpdate = scriptEnv.GetInPath<Action>(luaScript + ".Update");
        luaFixedUpdate = scriptEnv.GetInPath<Action>(luaScript + ".FixedUpdate");
        luaOnEnable = scriptEnv.GetInPath<Action>(luaScript + ".OnEnable");
        luaOnDisable = scriptEnv.GetInPath<Action>(luaScript + ".OnDisable");
        luaOnDestroy = scriptEnv.GetInPath<Action>(luaScript + ".OnDestroy");
        luaOnRevPacket = scriptEnv.GetInPath<Action>(luaScript + ".OnRevPacket");
    }

    #region interaction

    public void OnRevPacket(PacketDistributed packet)
    {
        if (luaOnRevPacket == null)
            return;

        scriptEnv.Set("RevPacket", packet);
        luaOnRevPacket();
    }

    public void CloseUI()
    {
        gameObject.SetActive(false);
    }

    #endregion

    #region lua tool

    public static GameObject InstantiateSubItem(GameObject subItemPre, GameObject parent)
    {
        var newItem = Instantiate(subItemPre);
        newItem.transform.SetParent(parent.transform);
        newItem.transform.localScale = Vector3.one;
        newItem.transform.localPosition = Vector3.zero;
        newItem.transform.localRotation = Quaternion.Euler(Vector3.zero);
        newItem.SetActive(true);
        return newItem;
    }

    public static void ClearAllChildItem(GameObject parent)
    {
        var children = new List<Transform>();
        for (var i = 0; i < parent.transform.childCount; ++i) children.Add(parent.transform.GetChild(i));

        for (var i = 0; i < children.Count; ++i) Destroy(children[i].gameObject);
    }

    public static Tab_CommonItem GetCommonItem(int itemData)
    {
        var commonItem = TableManager.GetCommonItemByID(itemData);
        return commonItem;
    }

    public static string GetStrDictionary(int strDictionary)
    {
        return StrDictionary.GetActDictionaryString("#{" + strDictionary + "}");
    }

    public static Image GetChildImage(GameObject go, string childName)
    {
        var childGO = go.transform.Find(childName);
        if (string.IsNullOrEmpty(childName)) childGO = go.transform;

        return childGO.GetComponent<Image>();
    }

    public static void SetImage(GameObject go, string childName, string imageName)
    {
        var image = GetChildImage(go, childName);
        LoadAssetBundle.Instance.SetImageSprite(image, imageName);
    }

    public static void SetItemIcon(GameObject go, string childName, int itemData)
    {
        var commonItem = TableManager.GetCommonItemByID(itemData);
        SetImage(go, childName, commonItem.Icon);
    }

    public static Text GetChildText(GameObject go, string childName)
    {
        var childGO = go.transform.Find(childName);
        if (string.IsNullOrEmpty(childName)) childGO = go.transform;

        return childGO.GetComponent<Text>();
    }

    public static void SetText(GameObject go, string childName, string textStr)
    {
        var textGO = GetChildText(go, childName);
        textGO.text = textStr;
    }

    public static Obj_MainPlayer GetPlayerInfo()
    {
        return Singleton<ObjManager>.GetInstance().MainPlayer;
    }

    public LuaUIBehaviour GetChildUILua(string childName)
    {
        var childGO = transform.Find(childName);
        if (string.IsNullOrEmpty(childName)) childGO = transform;

        return childGO.GetComponent<LuaUIBehaviour>();
    }

    public static void SetCommonAward(GameObject itemGO, int awardType, int subType, int num)
    {
        var awardItem = new MarketingActAwardItem();
        awardItem.awardType = awardType;
        awardItem.awardSubType = subType;
        awardItem.awardNum = num;
        itemGO.GetComponent<MarketingCommonAward>().InitItem(awardItem);
    }

    #endregion

    #region

    public void CallScriptFunc(string funcName)
    {
        var func = scriptEnv.Get<string, Action>(funcName);
        if (func == null)
        {
            LogModule.ErrorLog("there is no script func name:" + funcName);
            return;
        }

        func();
    }

    public void CallScriptFuncAtPath(string funcName, params object[] funcParam)
    {
        var func = scriptEnv.GetInPath<LuaFunction>(funcName);
        if (func == null)
        {
            LogModule.ErrorLog("there is no script func name:" + funcName);
            return;
        }

        func.Call(funcParam);
    }

    public virtual GameObject GetInjectionObj(string name)
    {
        if (injectionGos != null)
            for (var i = 0; i < injectionGos.Length; ++i)
                if (injectionGos[i].name == name)
                    return injectionGos[i].value;

        return null;
    }

    #endregion
}