#if UNITY_EDITOR
namespace NiAkaDev.EzMirror.Editor
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using UdonSharpEditor;
    using UnityEditor;
    using UnityEngine;
    using UnityEngine.UI;
    using VRC.Dynamics;
    using VRC.SDK3.Components;
    using VRC.SDK3.Dynamics.Contact.Components;
    using VRC.SDKBase;
    using VRC.Udon;

    public partial class EzMirrorEditor : UnityEditor.Editor
    {
        private void DrawDeveloperOptions()
        {
            bool expanded = EditorPrefs.GetBool(DeveloperOptionsPrefsKey, false);
            EditorGUILayout.Space();
            bool newExpanded = EditorGUILayout.Foldout(
                expanded,
                L("DeveloperOptions", "開発者オプション"),
                true,
                EditorStyles.foldoutHeader
            );
            if (newExpanded != expanded)
                EditorPrefs.SetBool(DeveloperOptionsPrefsKey, newExpanded);
            if (!newExpanded)
                return;

            EditorGUILayout.Space();
            using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
            {
                EditorGUILayout.HelpBox(
                    L(
                        "DeveloperDescription",
                        "通常は触らない設定です。生成Materialは EzMirror ごとに専用化され、Prefab コピー後も他Prefabと共有されないよう自動再生成します。基盤Materialを差し替えたい場合だけ変更してください。"
                    ),
                    MessageType.Info
                );

                DrawDeveloperHealthActions();
                DrawDeveloperProfileMaintenance();
                DrawProfileMaterialGenerationControls();
                DrawDeveloperReferenceSettings();
                DrawDeveloperSwitchAnimatorSettings();
                DrawDeveloperPublicMethodHints();
                EnsureSerializedProfileArraySizes();
                for (int i = 1; i < profileBaseMaterials.arraySize; i++)
                {
                    DrawDeveloperMaterialRow(i);
                }

                EditorGUILayout.Space(4f);
                EditorGUILayout.LabelField(L("DeveloperDangerZone", "危険操作"), SectionHeaderStyle);
                EditorGUILayout.HelpBox(
                    L("DeveloperDangerZoneHelp", "生成物の掃除や強制再生成など、通常は不要で影響範囲が大きい操作です。対象を確認してから実行してください。"),
                    MessageType.Warning
                );
                if (GUILayout.Button(L("RegenerateFromBaseButton", "基盤Materialから安定パスへ再生成")))
                {
                    Material[] materials = GetUniqueProfileFadeMaterials();
                    TryGetCommonFadeRanges(materials, out float distanceRange, out float horizontalRange);
                    ApplyTriggerAlignedFadeToTargets(distanceRange, horizontalRange, true);
                    GUIUtility.ExitGUI();
                }
            }
        }

        private void DrawDeveloperProfileMaintenance()
        {
            using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
            {
                EditorGUILayout.LabelField(
                    L("DeveloperProfileMaintenance", "プロファイル保守"),
                    SectionHeaderStyle
                );
                EditorGUILayout.HelpBox(
                    L("DeveloperProfileMaintenanceHelp", "プロファイルアセット生成や内部配列の整合など、通常の設置では不要な保守操作です。"),
                    MessageType.Info
                );
                DrawDefaultProfileAssetControls();
                if (GUILayout.Button(L("AlignProfileArraysButton", "プロファイル関連配列の数を揃える")))
                    EnsureSerializedProfileArraySizes();
            }
        }

        private void DrawDeveloperHealthActions()
        {
            EzMirror mirror = target as EzMirror;
            if (mirror == null)
                return;

            using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
            {
                EditorGUILayout.LabelField(
                    L("DeveloperHealthActions", "設定チェック操作"),
                    SectionHeaderStyle
                );
                EditorGUILayout.HelpBox(
                    L("DeveloperHealthActionsHelp", "READMEを開く、保存キー生成、検証、修復、マテリアル再生成などの保守向け操作です。通常の設置では必要になった時だけ使ってください。"),
                    MessageType.Info
                );

                EzMirrorValidationReport report = EzMirrorDistributionValidator.ValidateMirrors(
                    new[] { mirror }
                );
                AddSelectedDuplicatePersistKeyWarning(report, mirror);

                using (new EditorGUILayout.HorizontalScope())
                {
                    if (GUILayout.Button(L("HealthValidateSelected", "Validate Selected")))
                        LogHealthReport(report);
                    if (GUILayout.Button(L("HealthRepairSafe", "Repair Safe Issues")))
                        RepairHealthIssues(mirror);
                    if (GUILayout.Button(L("HealthRegenerateMaterials", "Regenerate Materials")))
                        RegenerateHealthMaterials(mirror);
                }

                using (new EditorGUILayout.HorizontalScope())
                {
                    if (GUILayout.Button(L("HealthGeneratePersistKey", "Generate Persist Key")))
                    {
                        EzMirrorRepairUtility.GeneratePersistKeyForMirror(mirror, true);
                        serializedObject.Update();
                    }
                    if (GUILayout.Button(L("HealthOpenReadme", "Open README")))
                        OpenReadme();
                }
            }
        }

        private void DrawDeveloperReferenceSettings()
        {
            using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
            {
                EditorGUILayout.LabelField(L("DeveloperReferences", "基本参照"), SectionHeaderStyle);
                EditorGUILayout.HelpBox(
                    L("DeveloperReferencesHelp", "通常ステップからは外した内部参照です。自動セットアップで解決できない特殊構成だけ手動で調整してください。"),
                    MessageType.Info
                );
                DrawReferenceField(
                    profileMirror,
                    L("ReferenceMirror", "ミラー本体"),
                    L("ReferenceMirrorHint", "VRCMirrorReflection。プロファイルの画質設定をここに適用します。")
                );
                DrawReferenceField(
                    profileRenderer,
                    L("ReferenceRenderer", "表示用Renderer"),
                    L("ReferenceRendererHint", "Material と表示ON/OFFを切り替える Renderer です。")
                );
                DrawReferenceField(
                    triggerCollider,
                    L("ReferenceRange", "表示範囲"),
                    L("ReferenceRangeHint", "プレイヤーが入ると Mirror を表示する範囲です。")
                );
                DrawReferenceField(
                    uiToggle,
                    L("ReferenceToggle", "切替UI Toggle"),
                    L("ReferenceToggleHint", "OnValueChanged から SelectNextFromUgui を呼び出す UI です。未使用なら空で構いません。")
                );
                DrawReferenceField(
                    inputProxy,
                    L("ReferenceInputProxy", "Contact入力プロキシ"),
                    L("ReferenceInputProxyHint", "手で触る切替を本体へ中継する ContactInput 上の UdonSharp です。")
                );
                DrawReferenceField(
                    interactInputProxy,
                    L("ReferenceInteractProxy", "Use入力プロキシ"),
                    L("ReferenceInteractProxyHint", "Use切替を本体へ中継する InteractInput 上の UdonSharp です。")
                );
                DrawReferenceField(
                    inputHitboxCollider,
                    L("ReferenceInteractHitbox", "Interact判定"),
                    L("ReferenceInteractHitboxHint", "Interact 用の非Trigger BoxColliderです。")
                );
                DrawReferenceField(
                    contactReceiver,
                    L("ReferenceContact", "Contact判定"),
                    L("ReferenceContactHint", "手の接触で切り替える VRCContactReceiver です。")
                );
                EditorGUILayout.PropertyField(triggerRefreshInterval, LC("TriggerRefreshIntervalLabel", "表示範囲の再判定間隔"));

                if (GUILayout.Button(L("WireToggleButton", "Toggle の OnValueChanged を自動接続")))
                {
                    ApplyToTargets(WireToggleEvent, "Wire EzMirror Toggle");
                    GUIUtility.ExitGUI();
                }
                if (GUILayout.Button(L("RepairInputButton", "切替入力を自動修復")))
                {
                    ApplyToTargets(EnsureInputControls, "Repair EzMirror Inputs");
                    GUIUtility.ExitGUI();
                }
            }
        }

        private void DrawDeveloperSwitchAnimatorSettings()
        {
            using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
            {
                EditorGUILayout.LabelField(
                    L("DeveloperSwitchAnimator", "3Dスイッチ Animator"),
                    SectionHeaderStyle
                );
                EditorGUILayout.HelpBox(
                    L(
                        "DeveloperSwitchAnimatorHelp",
                        "3Dスイッチ用の高度な設定です。通常はStep2の自動修復だけで十分です。独自Animator Controllerを使う場合だけ調整してください。"
                    ),
                    MessageType.Info
                );

                EditorGUILayout.PropertyField(
                    switchAnimator,
                    LC("ReferenceSwitchAnimator", "3Dスイッチ Animator")
                );
                EditorGUILayout.PropertyField(
                    switchAnimatorProfileIndexParameter,
                    LC("SwitchAnimatorProfileIndexParameter", "プロファイル番号パラメーター")
                );
                EditorGUILayout.PropertyField(
                    switchAnimatorStateParameter,
                    LC("SwitchAnimatorStateParameter", "状態パラメーター")
                );
                EditorGUILayout.PropertyField(
                    switchAnimatorPressParameter,
                    LC("SwitchAnimatorPressParameter", "押し込みパラメーター")
                );

                using (new EditorGUI.DisabledScope(true))
                {
                    EditorGUILayout.PropertyField(
                        switchAnimatorCanSetProfileIndex,
                        LC("SwitchAnimatorCanSetProfileIndex", "プロファイル番号を送れる")
                    );
                    EditorGUILayout.PropertyField(
                        switchAnimatorCanSetState,
                        LC("SwitchAnimatorCanSetState", "状態を送れる")
                    );
                    EditorGUILayout.PropertyField(
                        switchAnimatorCanSetPress,
                        LC("SwitchAnimatorCanSetPress", "押し込みを送れる")
                    );
                }

                using (new EditorGUILayout.HorizontalScope())
                {
                    if (GUILayout.Button(L("ValidateSwitchAnimatorButton", "Animator設定を検証")))
                    {
                        ApplyToTargets(ValidateSwitchAnimatorOnly, "Validate EzMirror Switch Animator");
                        serializedObject.Update();
                    }
                    if (GUILayout.Button(L("ResetSwitchAnimatorDefaultsButton", "既定値に戻して修復")))
                    {
                        ApplyToTargets(ResetSwitchAnimatorToDefaults, "Reset EzMirror Switch Animator");
                        serializedObject.Update();
                    }
                }
            }
        }

        private static void ValidateSwitchAnimatorOnly(EzMirror mirror)
        {
            if (mirror == null)
                return;
            ResetSwitchAnimatorParameterNamesIfEmpty(mirror);
            ValidateSwitchAnimatorParameters(mirror);
            EditorUtility.SetDirty(mirror);
            PrefabUtility.RecordPrefabInstancePropertyModifications(mirror);
        }

        private static void ResetSwitchAnimatorToDefaults(EzMirror mirror)
        {
            if (mirror == null)
                return;
            mirror.useSwitchAnimator = true;
            mirror.switchAnimatorProfileIndexParameter =
                EzMirror.DefaultSwitchAnimatorProfileIndexParameter;
            mirror.switchAnimatorStateParameter = EzMirror.DefaultSwitchAnimatorStateParameter;
            mirror.switchAnimatorPressParameter = EzMirror.DefaultSwitchAnimatorPressParameter;
            RepairSwitchAnimatorSetup(mirror);
        }

        private static void DrawDeveloperPublicMethodHints()
        {
            using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
            {
                EditorGUILayout.LabelField(
                    L("DeveloperMethods", "他ギミックから呼び出す公開メソッド"),
                    SectionHeaderStyle
                );
                EditorGUILayout.HelpBox(
                    L("DeveloperMethodsHelp", "UI や SendCustomEvent からは引数なしの操作だけを呼び出します。特定プロファイルを直接選びたい場合は、外部 UdonSharp から EzMirror 参照を持ち、SelectProfile(int profileIndex) を呼び出してください。"),
                    MessageType.Info
                );

                DrawCopyableSingleLine(L("MethodUguiNext", "uGUI Toggleから次へ"), "SendCustomEvent(\"SelectNextFromUgui\")");
                DrawCopyableSingleLine(L("MethodNext", "次のプロファイルへ（外部制御用）"), "SendCustomEvent(\"SelectNext\")");
                DrawCopyableSingleLine(L("MethodOff", "Offにする"), "SendCustomEvent(\"TurnOff\")");
                DrawCopyableSingleLine(L("MethodReset", "初期状態へ戻す"), "SendCustomEvent(\"ResetToDefault\")");
                DrawCopyableSingleLine(L("MethodSelectProfile", "特定プロファイルを選ぶ"), "ezMirror.SelectProfile(4);");
                DrawCopyableSelectableLabel(
                    L("UdonSharpExample", "UdonSharp 例"),
                    L("UdonSharpExampleCode", "// ezMirror は EzMirror コンポーネント参照です。\n")
                        + "ezMirror.SelectNext();\n"
                        + L("UdonSharpExampleSelectLine", "ezMirror.SelectProfile(4); // 0=Off, 1=プロファイル1\n")
                        + "ezMirror.ResetToDefault();",
                    CopyableCodeHeight
                );
            }
        }

        private static void DrawCopyableSingleLine(string label, string value)
        {
            using (new EditorGUILayout.HorizontalScope())
            {
                Rect rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight);
                Rect valueRect = EditorGUI.PrefixLabel(rect, new GUIContent(label));
                EditorGUI.SelectableLabel(valueRect, value, EditorStyles.textField);
                if (GUILayout.Button(L("CopyButton", "コピー"), GUILayout.Width(CopyButtonWidth)))
                    EditorGUIUtility.systemCopyBuffer = value;
            }
        }

        private static void DrawCopyableSelectableLabel(string label, string value, float height)
        {
            EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
            using (new EditorGUILayout.HorizontalScope())
            {
                EditorGUILayout.SelectableLabel(value, EditorStyles.textArea, GUILayout.MinHeight(height));
                if (GUILayout.Button(L("CopyButton", "コピー"), GUILayout.Width(CopyButtonWidth), GUILayout.Height(height)))
                    EditorGUIUtility.systemCopyBuffer = value;
            }
        }

        private void DrawDeveloperMaterialRow(int index)
        {
            using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
            {
                EditorGUILayout.LabelField(LF("ProfileTitlePrefix", "プロファイル {0}", index), EditorStyles.boldLabel);
                EditorGUILayout.PropertyField(
                    profileBaseMaterials.GetArrayElementAtIndex(index),
                    LC("BaseMaterialLabel", "基盤Material")
                );

                using (new EditorGUI.DisabledScope(true))
                {
                    EditorGUILayout.PropertyField(
                        profileMaterials.GetArrayElementAtIndex(index),
                        LC("GeneratedMaterialLabel", "生成Material")
                    );
                }
            }
        }
    }
}
#endif
