using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UnityEngine;
using System;
using XLua;
using Module.Log;


public class LuaUIItemBase : UIItemBase
//public class LuaUIItemBase : UIItemBase, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler,IPointerExitHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, IDropHandler
{
    public delegate void voidObject(object obj);
    public delegate void voidLuaUIItemBase(LuaUIItemBase obj);

    public string luaScript;
    public LuaParamGO[] injectionGos;

    internal static float lastGCTime = 0;
    internal const float GCInterval = 1; //1 second 

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

    private Action luaRefresh;
    private voidObject luaRefreshWithTab;
    private Action luaOnPointerClick;
    private Action<PointerEventData> luaOnItemClick;
    private Action luaShow;
    private voidObject luaShowWithTab;

    private Action<PointerEventData> luaOnPointerDown;
    private Action<PointerEventData> luaOnPointerUp;
    private Action<PointerEventData> luaOnPointerEnter;
    private Action<PointerEventData> luaOnPointerExit;
    private Action<PointerEventData> luaOnBeginDrag;
    private Action<PointerEventData> luaOnDrag;
    private Action<PointerEventData> luaOnEndDrag;
    private Action<PointerEventData> luaOnDrop;

    private bool hasAwake = false;
    protected LuaTable scriptEnv;

    public virtual void SetValue(string paramName, object value)
    {
        if (scriptEnv != null)
        {
            scriptEnv.Set(paramName, value);
        }
    }

    public virtual void SetValueAtPath(string paramName, object value)
    {
        CallScriptFuncAtPath("SetValue", paramName, value);
    }

    public virtual object GetValueAtPath(string valueName)
    {
        if(scriptEnv != null)
        {
            return scriptEnv.GetInPath<object>(luaScript + "." + valueName);
        }
        else
        {
            return null;
        }
    }

    public virtual object GetValue(string valueName)
    {
        if (scriptEnv != null)
        {
            return scriptEnv.Get<object>(valueName);
        }
        else
        {
            return null;
        }
    }

    public override void Init()
    {
        if (luaScript == null)
            return;

        if (scriptEnv == null)
        {
            scriptEnv = LuaMain.luaEnv.NewTable();
        }

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

        scriptEnv.Set("self", this.gameObject);
        foreach (var injection in injectionGos)
        {
            scriptEnv.Set(injection.name, injection.value);
        }

        TextAsset 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");

        // UIItembase
        luaRefresh = scriptEnv.GetInPath<Action>(luaScript + ".Refresh");
        luaRefreshWithTab = scriptEnv.GetInPath<voidObject>(luaScript + ".RefreshWithTab");
        luaOnPointerClick = scriptEnv.GetInPath<Action>(luaScript + ".OnPointerClick");
        luaOnItemClick = scriptEnv.GetInPath<Action<PointerEventData>>(luaScript + ".OnItemClick");
        luaShow = scriptEnv.GetInPath<Action>(luaScript + ".Show");
        luaShowWithTab = scriptEnv.GetInPath<voidObject>(luaScript + ".ShowWithTab");

        // UnityEngine.EventSystems
        luaOnPointerDown = scriptEnv.GetInPath<Action<PointerEventData>>(luaScript + ".OnPointerDown");
        luaOnPointerUp = scriptEnv.GetInPath<Action<PointerEventData>>(luaScript + ".OnPointerUp");
        luaOnPointerEnter = scriptEnv.GetInPath<Action<PointerEventData>>(luaScript + ".OnPointerEnter");
        luaOnPointerExit = scriptEnv.GetInPath<Action<PointerEventData>>(luaScript + ".OnPointerExit");
        luaOnBeginDrag = scriptEnv.GetInPath<Action<PointerEventData>>(luaScript + ".OnBeginDrag");
        luaOnDrag = scriptEnv.GetInPath<Action<PointerEventData>>(luaScript + ".OnDrag");
        luaOnEndDrag = scriptEnv.GetInPath<Action<PointerEventData>>(luaScript + ".OnEndDrag");
        luaOnDrop = scriptEnv.GetInPath<Action<PointerEventData>>(luaScript + ".OnDrop");
    }

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

        hasAwake = true;

        Init();

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

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

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

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

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

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

    protected virtual void OnDestroy()
    {
        if (luaOnDestroy != null)
        {
            luaOnDestroy();
        }

        luaAwake = null;
        luaStart = null;
        luaUpdate = null;
        luaFixedUpdate = null;
        luaOnEnable = null;
        luaOnDisable = null;
        luaOnDestroy = null;

        luaRefresh = null;
        luaRefreshWithTab = null;
        luaOnPointerClick = null;
        luaOnItemClick = null;
        luaShow = null;
        luaShowWithTab = null;

        luaOnPointerDown = null;
        luaOnPointerUp = null;
        luaOnPointerEnter = null;
        luaOnPointerExit = null;
        luaOnBeginDrag = null;
        luaOnDrag = null;
        luaOnEndDrag = null;
        luaOnDrop = null;

        scriptEnv.Dispose();
    }

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

        func.Call(funcParam);
    }

    #region ItemBase

    public override void Show()
    {
        if(luaShow != null)
        {
            luaShow.Invoke();
        }
    }

    public override void Show(Hashtable hash)
    {
        System.Object info = hash["InitObj"];
        ShowWithTab(info);
    }

    public virtual void ShowWithTab(System.Object luaData)
    {
        if(luaShowWithTab != null)
        {
            _InitInfo = luaData;
            luaShowWithTab.Invoke(luaData);
        }
    }

    public override void Refresh()
    {
        if (luaRefresh != null)
        {
            luaRefresh.Invoke();
        }
    }

    public virtual void Refresh(System.Object luaData)
    {
        if (luaRefreshWithTab != null)
        {
            luaRefreshWithTab.Invoke(luaData);
        }
    }

    public override void OnPointerClick(PointerEventData eventData)
    {
        OnItemClick();

        ButtonPlaySound btnPlay = GetComponent<ButtonPlaySound>();
        if (btnPlay != null)
            btnPlay.PlaySound();

        if (luaOnItemClick != null)
        {
            luaOnItemClick(eventData);
        }
    }

    public override void OnItemClick()
    {
        if (_ClickEvent != null)
        {
            _ClickEvent(_InitInfo);
        }

        if (_PanelClickEvent != null)
        {
            _PanelClickEvent(this);
        }
    }

    #endregion

    #region UnityEngine.EventSystems

    public void OnPointerDown(PointerEventData eventData)
    {
        if(luaOnPointerDown != null)
        {
            luaOnPointerDown(eventData);
        }
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        if (luaOnPointerUp != null)
        {
            luaOnPointerUp(eventData);
        }
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        if (luaOnPointerEnter != null)
        {
            luaOnPointerEnter(eventData);
        }
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        if (luaOnPointerExit != null)
        {
            luaOnPointerExit(eventData);
        }
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        if (luaOnBeginDrag != null)
        {
            luaOnBeginDrag(eventData);
        }
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (luaOnDrag != null)
        {
            luaOnDrag(eventData);
        }
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (luaOnEndDrag != null)
        {
            luaOnEndDrag(eventData);
        }
    }

    public void OnDrop(PointerEventData eventData)
    {
        if (luaOnDrop != null)
        {
            luaOnDrop(eventData);
        }
    }

    #endregion
}