using System;
using System.Collections.Generic;
using System.Reflection;

namespace XGame.Editor.Build
{
    /// <summary>
    /// 准备开始构建安装包，仅在无参的静态方法上添加有效
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public class PrepareBuildCallBackAttribute : Attribute
    {

    }

    /// <summary>
    /// 安装包构建完成，仅在带有一个int类型参数的静态方法上添加有效
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public class BuildCompletedCallBackAttribute : Attribute
    {

    }

    internal static class BuildEventHelper
    {
        private static void AddMethods<T>(List<MethodInfo> methodInfos, Type type) where T : Attribute
        {
            var methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
            foreach (var method in methods)
            {
                var attr = method.GetCustomAttribute<T>(false);
                if (null == attr) continue;
                methodInfos.Add(method);
            }
        }

        private static List<MethodInfo> CollectCallBackMethod<T>() where T : Attribute
        {
            List<MethodInfo> methodInfos = new List<MethodInfo>();
            try
            {
                var assemblies = AppDomain.CurrentDomain.GetAssemblies();
                foreach (var assembly in assemblies)
                {
                    var assemblyName = assembly.GetName().Name;
                    //UnityEngine.Debug.Log($"CollectCallBackMethod assembly Name:{assemblyName}");
                    if (assemblyName.StartsWith("Unity", StringComparison.Ordinal) || assemblyName.StartsWith("System", StringComparison.Ordinal))
                    {
                        continue;
                    }
                    var types = assembly.GetTypes();
                    foreach (var type in types)
                    {
                        AddMethods<T>(methodInfos, type);
                    }
                }
            }
            catch (Exception ex)
            {
                BuildLog.Exception(ex);
            }
            return methodInfos;
        }

        /// <summary>
        /// 通知即将开始构建
        /// </summary>
        internal static void InvokeBeforeBuild()
        {
            var methodInfos = CollectCallBackMethod<PrepareBuildCallBackAttribute>();
            object[] parameters = null;
            foreach (var method in methodInfos)
            {
                try
                {
                    method.Invoke(null, parameters);
                }
                catch (Exception e)
                {
                    BuildLog.Error("PrepareBuildCallBack failed: {0}.{1}", method.ReflectedType.FullName, method.Name);
                    BuildLog.Exception(e);
                }
            }
        }

        /// <summary>
        /// 通知构建已结束
        /// </summary>
        internal static void InvokeAfterBuild(int code)
        {
            var methodInfos = CollectCallBackMethod<BuildCompletedCallBackAttribute>();
            object[] parameters = new object[1] { code };
            foreach (var method in methodInfos)
            {
                try
                {
                    method.Invoke(null, parameters);
                }
                catch (Exception e)
                {
                    BuildLog.Error("BuildCompletedCallBack failed: {0}.{1}", method.ReflectedType.FullName, method.Name);
                    BuildLog.Exception(e);
                }
            }
        }
    }
}
