using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using System.Collections.Generic;
using Module.Log;

/// <summary>
/// 基础加载任务类型,用于加载Ui或者其他Bundle名字不额外携带AssetName的类型
/// </summary>
public class BaseLoadTask<TItem, TLoadData, TLoadTask> where TItem : Component where TLoadData : BaseLoadData<TItem, TLoadData> where TLoadTask : BaseLoadTask<TItem, TLoadData, TLoadTask>
{
    public string BundleName { get; private set; }
    public string PrefabName { get; private set; }
    public bool Archive { get; private set; }
    public readonly List<TLoadData> taskListeners = new List<TLoadData>();
    public GameObject Prefab { get; private set; }
    private event UnityAction<TLoadTask> OnLoadComplete;

    // 注:实际Init逻辑上和构造在一起,但是构造只能限制为无参,因此只能分开
    public void Init(TLoadData taskStarter, string bundleName, string prefabName, bool archive, UnityAction<TLoadTask> onLoadComplete)
    {
        if (taskStarter != null)
            taskListeners.Add(taskStarter);
        OnLoadComplete = onLoadComplete;
        BundleName = bundleName;
        PrefabName = prefabName;
        Archive = archive;
        Load(BundleName, PrefabName);
    }

    public void Load(string pBundleName, string pPrefabName)
    {
        CommonUtility.LoadAssetInstance(pBundleName, pPrefabName, OnLoadTaskComplete, Archive);
    }

    public void CancelLoad(string pBundleName, string pPrefabName)
    {
        LoadAssetBundle.Instance.UnloadAsset(pBundleName, pPrefabName);
    }
    
    public bool Match(string pBundleName, string pPrefabName)
    {
        return string.Equals(BundleName, pBundleName, StringComparison.InvariantCultureIgnoreCase) &&
               string.Equals(PrefabName, pPrefabName, StringComparison.InvariantCulture);
    }
    
    /// <summary>
    /// 释放加载流程
    /// </summary>
    // 注:加载仍然会执行,但是加载任务引用对象可以正常析构
    public void ReleaseLoad()
    {
        taskListeners.Clear();
        Prefab = null;
        CancelLoad(BundleName, PrefabName);
        OnLoadComplete = null;
    }

    /// <summary>
    /// 检查加载任务是否重复,如果重复就添加到加载回调中
    /// </summary>
    public bool TryAddListener(TLoadData taskListener, string bundleName, string prefabName)
    {
        var valid = Match(bundleName, prefabName);
        if (valid && !taskListeners.Contains(taskListener))
            taskListeners.Add(taskListener);
        return valid;
    }
    
    public void RemoveListener(Predicate<TLoadData> predicate)
    {
        for (var i = taskListeners.Count - 1; i >= 0; i--)
            if (predicate(taskListeners[i]))
                taskListeners.RemoveAt(i);
    }

    protected void OnLoadTaskComplete(string modelName, GameObject resObj, Hashtable hashParam)
    {
        if (resObj == null)
            LogModule.ErrorLog(string.Format("无法加载Prefab: bundle = {0}, name = {1}", BundleName, PrefabName));
        else
        {
            Prefab = resObj;
            if (OnLoadComplete != null)
                OnLoadComplete.Invoke((TLoadTask) this);
            // 加载流程完成,等待所需组件被初始化
            //Prefab = Object.Instantiate(resObj);
            // 普通Prefab的处理方式 - 丢在根路径,不主动删除
            //Object.DontDestroyOnLoad(Prefab);
            //Prefab.gameObject.SetActive(false);
        }
    }
//    // 每一帧获得一次Tick,检查是否能够获得
//    private void OnUpdateTick()
//    {
//        if (Prefab == null || OnLoadComplete == null)
//            GameManager.gameManager.OnUpdate -= OnUpdateTick;
//        else
//            FinishTaskIfComponentLoad();
//    }
//
//    private bool FinishTaskIfComponentLoad()
//    {
//        var result = Prefab.HasComponent<TItem>();
//        if (Prefab.HasComponent<TItem>())
//        {
//            GameManager.gameManager.OnUpdate -= OnUpdateTick;
//            OnLoadComplete((TLoadTask) this);
//        }
//
//        return result;
//    }
}

public class BaseLoadData<TItem, TLoadData> where TItem : Component where TLoadData : BaseLoadData<TItem, TLoadData>
{
    public readonly Transform root;
    public readonly UnityAction<TItem, TLoadData> callback;
    public BaseLoadData(Transform root, UnityAction<TItem, TLoadData> callback)
    {
        this.root = root;
        this.callback = callback;
    }
}
//
///// <summary>
///// 仿制原来的GameObject加载流程 - bundleName = bundleName + assetName
///// </summary>
//public class GameObjectLoadTask<TItem, TLoadData, TLoadTask> : BaseLoadTask<TItem, TLoadData, TLoadTask> where TItem : Component where TLoadData : BaseLoadData<TItem, TLoadData> where TLoadTask : BaseLoadTask<TItem, TLoadData, TLoadTask>
//{
//    public bool archive;
//    
//    public override void Load(string pBundleName, string pPrefabName)
//    {
//        // 使用通用的加载GameObject接口,加载完成后释放
//        CommonUtility.LoadGameObjectInstance(pBundleName, pPrefabName, OnLoadTaskComplete, archive);
//    }
//
//    public override void CancelLoad(string pBundleName, string pPrefabName)
//    {
//        LoadAssetBundle.Instance.UnloadAssetWithPathFix(pBundleName, pPrefabName);
//    }
//}