using System;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;

namespace CatsUdonTools.Editor
{
    /// <summary>
    /// 入稿者がシーン上の Export GameObject を指定し、CatsUdonExporter 階層の Prefab 化と
    /// 依存アセットごとの unitypackage 書き出しを行うためのウィンドウ。
    /// エンコードと構成検証はしない（Worker 側の Unity が行う）。ここでは書き出しの指示までを担当する。
    /// 複数のクリップの Controller（テンプレート MultiClip）を表から作る欄も持つ（MultiClipAnimationSection）
    /// </summary>
    public class UnityPackagePublisherWindow : EditorWindow
    {
        private bool isBusy;
        private Vector2 scrollPosition;
        private string statusMessage = "Idle";
        private string exportError = "";


        private const string PackageNamePrefsKey = "RemoteModelPublisher.PackageName";

        private GameObject exportTarget;
        private string packageName = CatsUdonSubmissionPackager.DefaultPackageName;

        // 複数のクリップの表。ドメインリロードと Undo をまたいで残すためシリアライズする
        [SerializeField] private MultiClipAnimationSection animationSection = new MultiClipAnimationSection();

        [MenuItem("CatsUdon/Tools/UnityPackage Publisher")]
        public static void Open()
        {
            GetWindow<UnityPackagePublisherWindow>("UnityPackage Publisher");
        }

        private void OnEnable()
        {
            packageName = EditorPrefs.GetString(PackageNamePrefsKey, CatsUdonSubmissionPackager.DefaultPackageName);
            Undo.undoRedoPerformed += Repaint;
        }

        private void OnDisable()
        {
            Undo.undoRedoPerformed -= Repaint;
        }

        private void OnGUI()
        {
            // 窓が低くても Export まで辿り着けるようにスクロールさせる
            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
            DrawTemplateSection();
            EditorGUILayout.Space(8);
            DrawInputSection();
            EditorGUILayout.Space(8);
            DrawAnimationSection();
            EditorGUILayout.Space(8);
            DrawExportSection();
            EditorGUILayout.EndScrollView();
        }

        private void DrawTemplateSection()
        {
            EditorGUILayout.LabelField("Template", EditorStyles.boldLabel);
            if (GUILayout.Button("Create CatsUdonExporter"))
            {
                exportTarget = CatsUdonExporterTemplateAuthoring.CreateOrSelect();
            }
        }

        private void DrawInputSection()
        {
            EditorGUILayout.LabelField("Input", EditorStyles.boldLabel);
            exportTarget = (GameObject)EditorGUILayout.ObjectField("Export GameObject", exportTarget, typeof(GameObject), true);
            if (exportTarget == null)
            {
                EditorGUILayout.HelpBox("Create CatsUdonExporter でテンプレートを作り、その中にアバターを置いて CatsUdonExporter を指定してください。", MessageType.Info);
            }

            DrawPackageNameField();
        }

        private void DrawAnimationSection()
        {
            if (animationSection == null)
            {
                animationSection = new MultiClipAnimationSection();
            }

            animationSection.Draw(this, exportTarget);
        }

        private void DrawPackageNameField()
        {
            EditorGUI.BeginChangeCheck();
            packageName = EditorGUILayout.TextField("Package Name", packageName);
            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetString(PackageNamePrefsKey, packageName);
            }

            if (IsPackageNameInvalidCharacter())
            {
                EditorGUILayout.HelpBox("Package Name は英数字と - _ のみにしてください。", MessageType.Warning);
            }
        }

        private bool IsPackageNameInvalidCharacter()
        {
            return Regex.IsMatch(packageName.Trim(), CatsUdonSubmissionPackager.PackageNameInvalidCharacterRule);
        }

        private bool IsPackageNameValid()
        {
            return !string.IsNullOrEmpty(packageName.Trim()) && !IsPackageNameInvalidCharacter();
        }

        private void DrawExportSection()
        {
            var blocked = isBusy || exportTarget == null || !IsPackageNameValid() || EditorApplication.isPlayingOrWillChangePlaymode;
            using (new EditorGUI.DisabledScope(blocked))
            {
                if (GUILayout.Button("Export UnityPackage"))
                {
                    ExportPackage();
                }
            }

            EditorGUILayout.Space(4);
            EditorGUILayout.LabelField("Status", EditorStyles.boldLabel);
            EditorGUILayout.LabelField(statusMessage);

            if (!string.IsNullOrEmpty(exportError))
            {
                EditorGUILayout.HelpBox(exportError, MessageType.Error);
            }
        }

        private void ExportPackage()
        {
            if (isBusy)
            {
                return;
            }

            isBusy = true;
            exportError = "";

            try
            {
                statusMessage = "Building UnityPackage...";
                Repaint();

                var packageResult = CatsUdonSubmissionPackager.BuildUnityPackage(exportTarget, packageName);
                EditorUtility.RevealInFinder(packageResult.PackagePath);

                statusMessage = $"Completed: {Path.GetFileName(packageResult.PackagePath)}";
            }
            catch (Exception ex)
            {
                statusMessage = "Failed";
                exportError = ex.Message;
                Debug.LogError(ex);
            }
            finally
            {
                isBusy = false;
                Repaint();
            }
        }
    }
}
