#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 DrawSetupChecklist(EzMirror mirror)
        {
            DrawSectionHeader("現在の状態");
            using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
            {
                DrawStatusRow(
                    HasRequiredReferences(mirror),
                    L("StatusReferencesTitle", "ミラー / 表示Renderer / 表示範囲"),
                    L("StatusReferencesHint", "未設定なら「基本セットアップを自動実行」を押してください。")
                );
                DrawStatusRow(
                    HasProfiles(mirror),
                    L("StatusProfilesTitle", "プロファイル一覧"),
                    L("StatusProfilesHint", "Off固定のプロファイル 0 と、最低1つの通常プロファイルが必要です。")
                );
                DrawStatusRow(
                    HasMobileAvailableProfile(mirror),
                    L("StatusMobileTitle", "Quest / Android / iOS 用プロファイル"),
                    L("StatusMobileHint", "PC専用ではない通常プロファイルを最低1つ残すと安全です。")
                );
                DrawStatusRow(
                    HasLqBackgroundObject(mirror),
                    L("StatusLqBackgroundTitle", "LQ 背景クリア球"),
                    L("StatusLqBackgroundHint", "LQプロファイルで Skybox を消したい場合に使います。")
                );
                DrawStatusRow(
                    IsToggleEventReady(mirror),
                    L("StatusToggleTitle", "切替UIの接続"),
                    L("StatusToggleHint", "Toggle がある場合は本体へ SendCustomEvent(SelectNextFromUgui) を接続します。")
                );
                DrawStatusRow(
                    HasInputProxy(mirror),
                    L("StatusInputTitle", "Interact / Contact 入力"),
                    L("StatusInputHint", "SwitchUI / InteractInput / ContactInput が無い場合は「切替入力を自動修復」を押してください。")
                );
            }
        }

        private static void DrawStatusRow(bool ok, string title, string hint)
        {
            DrawColoredStatusRow(ok, title, hint);
        }

        internal static void DrawColoredStatusRow(bool ok, string title, string hint)
        {
            using (new EditorGUILayout.HorizontalScope())
            {
                Color oldContentColor = GUI.contentColor;
                GUI.contentColor = ok ? StatusOkColor : StatusErrorColor;
                GUILayout.Label(
                    EzMirrorLocalization.Get(
                        ok ? "StatusOk" : "StatusNeedCheck",
                        ok ? "[OK]" : "[要確認]"
                    ),
                    StatusBadgeStyle,
                    GUILayout.Width(72)
                );
                EditorGUILayout.LabelField(title, StatusTitleStyle, GUILayout.Width(190));
                EditorGUILayout.LabelField(
                    ok
                        ? EzMirrorLocalization.Get("StatusReadyText", "設定済み")
                        : hint,
                    EditorStyles.wordWrappedLabel
                );
                GUI.contentColor = oldContentColor;
            }
        }

        private static bool IsReadyForBasicUse(EzMirror mirror)
        {
            return HasRequiredReferences(mirror) && HasProfiles(mirror) && HasMobileAvailableProfile(mirror);
        }

        private static string GetSetupMessage(EzMirror mirror)
        {
            if (!HasRequiredReferences(mirror))
                return EzMirrorLocalization.Get(
                    "SetupMissingRefs",
                    "主要参照が不足しています。「基本セットアップを自動実行」を押すと、子オブジェクトから自動で拾います。"
                );
            if (!HasProfiles(mirror))
                return EzMirrorLocalization.Get(
                    "SetupMissingProfiles",
                    "プロファイル 0（Off）と通常プロファイルが未設定です。HQ / 透明 / LQ などのプロファイルを追加してください。"
                );
            if (!HasMobileAvailableProfile(mirror))
                return EzMirrorLocalization.Get(
                    "SetupMissingMobile",
                    "通常プロファイルがすべてPC専用です。Quest / Android / iOS用にPC専用ではないプロファイルを1つ残してください。"
                );
            return EzMirrorLocalization.Get(
                "SetupReady",
                "基本設定は整っています。フェード距離と Trigger 境界は Scene Gizmo で確認してください。"
            );
        }

        private static bool HasRequiredReferences(EzMirror mirror)
        {
            return mirror != null
                && mirror.profileMirror != null
                && mirror.profileRenderer != null
                && mirror.triggerCollider != null;
        }

        private static bool HasProfiles(EzMirror mirror)
        {
            return GetRuntimeProfileCount(mirror) > 1;
        }

        private static bool HasMobileAvailableProfile(EzMirror mirror)
        {
            int profileCount = GetRuntimeProfileCount(mirror);
            if (profileCount <= 1)
                return false;

            for (int i = 1; i < profileCount; i++)
            {
                if (mirror.profilePcOnly == null || i >= mirror.profilePcOnly.Length || !mirror.profilePcOnly[i])
                    return true;
            }

            return false;
        }

        private static int GetRuntimeProfileCount(EzMirror mirror)
        {
            if (mirror == null || mirror.profileMaterials == null)
                return 0;
            return mirror.profileMaterials.Length;
        }

        private static bool HasLqBackgroundObject(EzMirror mirror)
        {
            if (mirror == null || mirror.profileActiveObjects == null)
                return false;
            for (int i = 0; i < mirror.profileActiveObjects.Length; i++)
            {
                GameObject target = mirror.profileActiveObjects[i];
                if (target != null && target.name == LqBackgroundObjectName)
                    return true;
            }
            return false;
        }

        private static bool HasInputProxy(EzMirror mirror)
        {
            return mirror != null
                && mirror.inputProxy != null
                && mirror.interactInputProxy != null
                && mirror.inputHitboxCollider != null
                && mirror.contactReceiver != null;
        }

        private static bool IsToggleEventReady(EzMirror mirror)
        {
            if (mirror == null || mirror.uiToggle == null)
                return true;

            UdonBehaviour backing = UdonSharpEditorUtility.GetBackingUdonBehaviour(mirror);
            if (backing == null)
                return false;

            Toggle toggle = mirror.uiToggle;
            for (int i = 0; i < toggle.onValueChanged.GetPersistentEventCount(); i++)
            {
                if (
                    toggle.onValueChanged.GetPersistentTarget(i) == backing
                    && toggle.onValueChanged.GetPersistentMethodName(i) == "SendCustomEvent"
                    && GetToggleStringArgument(toggle, i) == ToggleEventName
                )
                {
                    return true;
                }
            }

            return false;
        }

        private static string GetToggleStringArgument(Toggle toggle, int index)
        {
            SerializedObject serializedToggle = new SerializedObject(toggle);
            SerializedProperty property = serializedToggle.FindProperty(
                "onValueChanged.m_PersistentCalls.m_Calls.Array.data[" + index + "].m_Arguments.m_StringArgument"
            );
            return property == null ? string.Empty : property.stringValue;
        }
    }
}
#endif
