using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using XGame.Framework;

namespace XGame.Editor.Build
{
    [BuildCommand((uint)BuildCommandPriority.BuildPlayer)]
    class CmdBuildPlayer : BaseBuildCommand, ICommandExecuter
    {
        public BuildErrorCode Execute()
        {
            if ((Context.config.operations & BuildOperation.OnlyBuildAssets) != 0)
            {
                BuildLog.Log("CmdBuildPlayer OnlyBuildAssets.");
                return BuildErrorCode.CmdCompleted;
            }
            var disableScenes = DisableScenesWithoutLaunch();
            //校验打包的Scene
            string[] levels = GetLevelsFromBuildSettings();
            if (levels.Length == 0)
            {
                BuildLog.Error("No scene to build.");
                RevertScenes(disableScenes);
                return BuildErrorCode.NoActiveScene;
            }


            var option = BuildOptions.None;
            var type = Context.config.publishType;
            switch (type)
            {
                case PublishType.Debug:
                    option = BuildOptions.Development;
                    break;
                case PublishType.Release:
                    option = BuildOptions.None;
                    break;
                case PublishType.Profiler:
                    option = BuildOptions.Development;
                    break;
                default:
                    break;
            }

            //打包App
            var report = BuildPipeline.BuildPlayer(levels, Context.appOutputPath, Context.config.target, option);
            Enum.TryParse(report.summary.result.ToString(), out BuildErrorCode errorCode);
            if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded && report.steps != null)
            {
                foreach (var step in report.steps)
                {
                    if (step.messages != null)
                    {
                        foreach (var msg in step.messages)
                        {
                            if (msg.type == LogType.Error || msg.type == LogType.Exception)
                            {
                                BuildLog.Log($"Build Report Step:{step.name} LogType:{msg.type} Message:{msg.content}");
                            }
                        }
                    }
                }
            }
            BuildLog.Log($"Build App Finish. Result:{errorCode}");
            if (errorCode == BuildErrorCode.Succeeded && Context.config.editor.autoExplorer)
            {
                try
                {
                    System.Diagnostics.Process.Start("expLorer.exe", Path.GetFullPath(Context.config.project.outputPath));
                }
                catch (Exception ex)
                {
                    BuildLog.Error($"AutoExplorer failed. Path:{Context.config.project.outputPath}");
                    BuildLog.Exception(ex);
                }
            }
            RevertScenes(disableScenes);
            return errorCode == BuildErrorCode.Succeeded ? BuildErrorCode.CmdCompleted : errorCode;
        }

        private List<string> DisableScenesWithoutLaunch()
        {
            var scenes = new List<string>();
            var launchScene = GetLaunchScene();
            foreach (var scene in EditorBuildSettings.scenes)
            {
                if (!scene.enabled)
                {
                    continue;
                }
                var sceneName = Path.GetFileNameWithoutExtension(scene.path);
                if (sceneName != launchScene)
                {
                    scene.enabled = false;
                    scenes.Add(scene.path);
                }
            }
            return scenes;
        }
        private string GetLaunchScene()
        {
            var xgameConfig = XGameConfig.Load();
            if (xgameConfig != null)
            {
                return xgameConfig.launchSceneName;
            }
            return string.Empty;
        }
        private void RevertScenes(List<string> scenes)
        {
            foreach (var scene in EditorBuildSettings.scenes)
            {
                if (scenes.Contains(scene.path))
                {
                    scene.enabled = true;
                }
            }
        }
        private string[] GetLevelsFromBuildSettings()
        {
            List<string> levels = new List<string>();
            for (int i = 0; i < EditorBuildSettings.scenes.Length; ++i)
            {
                if (EditorBuildSettings.scenes[i].enabled)
                    levels.Add(EditorBuildSettings.scenes[i].path);
            }
            return levels.ToArray();
        }
    }
}
