using System;
using System.IO;
using System.Net;
using UnityEditor;
using UnityEngine;

namespace Combo
{
    public class ComboSDKWizard : EditorWindow
    {
        private static string SettingsPath => Configuration.GetConfigPath();
        public Configuration Settings { get; private set; } = null; // Set by OnEnable()
        string[] listItems = { "China", "Global" };
        int selectedEndpointIdx = -1;

        [MenuItem("ComboSDK/Wizard")]
        public static void OnMenuClick()
        {
            var ins = GetWindow<ComboSDKWizard>();
            ins.minSize = new Vector2(400, 200);

            ins.titleContent = new GUIContent("Combo SDK", "Combo SDK Settings");
        }

        private void OnEnable()
        {
            Settings = CreateOrLoadSettings();
            InitEndpointIdx();
        }
        private void OnGUI()
        {
            EditorGUILayout.Space();
            GUILayout.Label("SDK Settings", EditorStyles.boldLabel);

            EditorGUILayout.Space();
            EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 1), Color.gray);
            EditorGUILayout.Space();

            GUILayout.Label("Base Options", EditorStyles.boldLabel);
            EditorGUILayout.Space();

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("Game Id", GUILayout.Width(125));
            
            Settings.GameId = EditorGUILayout.TextField(Settings.GameId)?.Trim();
            EditorGUILayout.EndHorizontal();
            if (string.IsNullOrWhiteSpace(Settings.GameId))
            {
                EditorGUILayout.HelpBox("Combo SDK requires a GameId.", MessageType.Error);
            }

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("Publishable Key", GUILayout.Width(125));
            Settings.PublishableKey = EditorGUILayout.TextField(Settings.PublishableKey)?.Trim();
            EditorGUILayout.EndHorizontal();
            if (string.IsNullOrWhiteSpace(Settings.PublishableKey))
            {
                EditorGUILayout.HelpBox("Combo SDK requires a PublishableKey.", MessageType.Error);
            }

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("Endpoint", GUILayout.Width(125));
            Settings.Endpoint = GUILayout.TextField(Settings.Endpoint);
            var selected = GUILayout.SelectionGrid(selectedEndpointIdx, listItems, listItems.Length, GUILayout.Width(125));
            if (selectedEndpointIdx != selected) {
                selectedEndpointIdx = selected;
                UpdateEndpoint();
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();
            
            EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 1), Color.gray);
            EditorGUILayout.Space();

            GUILayout.Label("iOS", EditorStyles.boldLabel);
            EditorGUILayout.Space();

            Settings.EnableIOSPostBuild = EditorGUILayout.ToggleLeft("Enable iOS PostBuild", Settings.EnableIOSPostBuild);
            EditorGUILayout.Space();

            EditorGUI.BeginDisabledGroup(!Settings.EnableIOSPostBuild);

            EditorGUILayout.HelpBox("可填入 Combo SDK 配置文件与产物所在的目录路径，PostBuild 会将其自动装配至 Xcode Project", MessageType.Info);

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(new GUIContent("Combo SDK Dir", "填入包含 Combo SDK 配置文件及 SDK 产物的目录路径"), GUILayout.Width(125));
            Settings.IOSComboSDK = EditorGUILayout.TextField(Settings.IOSComboSDK);
            if (GUILayout.Button("Choose", GUILayout.Width(60)))
            {
                string selectedFolder = EditorUtility.OpenFolderPanel("Select ComboSDK Folder", "", "");
                if (!string.IsNullOrEmpty(selectedFolder))
                {
                    string projectPath = Application.dataPath;
                    string releasePath = GetRelativePath(projectPath, selectedFolder);
                    Settings.IOSComboSDK = releasePath;
                    Repaint();
                }
            }
            EditorGUILayout.EndHorizontal();

#if UNITY_IOS
            var XCFrameworksInfo = XCFrameworkUtility.CompareXCFrameworks();
            if (!string.IsNullOrWhiteSpace(XCFrameworksInfo))
            {
                EditorGUILayout.HelpBox(XCFrameworksInfo, MessageType.Error);
            }
#endif
            EditorGUI.EndDisabledGroup();

            EditorGUILayout.Space();
            EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 1), Color.gray);
            EditorGUILayout.Space();

            GUILayout.Label("Android", EditorStyles.boldLabel); 
            EditorGUILayout.Space();

            EditorGUI.BeginDisabledGroup(!Settings.EnableKeepRenderingOnPause);
            EditorGUILayout.HelpBox("勾选时，弹出 Combo SDK 界面 Unity 将不再停止渲染", MessageType.Info);
            EditorGUI.EndDisabledGroup();

            Settings.EnableKeepRenderingOnPause = EditorGUILayout.ToggleLeft("Enable Keep Rendering on Pause", Settings.EnableKeepRenderingOnPause);
            EditorGUILayout.Space();

            EditorGUILayout.Space();
            EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 1), Color.gray);
            
            EditorGUILayout.Space();
            GUILayout.Label("Windows", EditorStyles.boldLabel); 
            EditorGUILayout.Space();

            EditorGUILayout.HelpBox("请注意，这是一项自定义配置。如果您对 ComboSDK.json 文件路径没有特殊要求，则无需进行设置\n若需自定义 ComboSDK.json 文件路径，请将其放入自行创建的 ./Assets/XXX/Resources 目录下，并在下方指定该路径", MessageType.Info);

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(new GUIContent("Custom Path for ComboSDK.json", "填入 ComboSDK.json 文件的所在路径"), GUILayout.Width(190));
            Settings.WindowsComboSDKJsonPath = EditorGUILayout.TextField(Settings.WindowsComboSDKJsonPath);
            if (GUILayout.Button("Choose", GUILayout.Width(60)))
            {
                string selectedFile = EditorUtility.OpenFilePanel("Select ComboSDK.json", "", "json");
                if (!string.IsNullOrEmpty(selectedFile))
                {
                    string projectPath = Application.dataPath;
                    string releasePath = GetRelativePath(projectPath, selectedFile);
                    Settings.WindowsComboSDKJsonPath = releasePath;
                    Repaint();
                }
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();
            EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 1), Color.gray);
        }

        private void OnLostFocus()
        {
            // Make sure the actual config asset exists before validating/saving. Crashes the editor otherwise.
            if (!File.Exists(SettingsPath))
            {
                Debug.LogError("ComboSDK Settings could not been saved. The configuration asset is missing.");
                return;
            }
            EditorUtility.SetDirty(Settings);
            AssetDatabase.SaveAssets();
        }

        private void UpdateEndpoint() {
            if (selectedEndpointIdx == -1) return;

            switch(listItems[selectedEndpointIdx]) {
                case "China":
                    Settings.Endpoint = "https://api.seayoo.com";
                    return;
                case "Global":
                    Settings.Endpoint = "https://api.seayoo.io";
                    return;
            }
        }
        private void InitEndpointIdx() {
            switch(Settings.Endpoint) {
                case "https://api.seayoo.com":
                    selectedEndpointIdx = 0;
                    return;
                case "https://api.seayoo.io":
                    selectedEndpointIdx = 1;
                    return;
                default:
                    selectedEndpointIdx = -1;
                    return;
            }
        }

        internal static Configuration CreateOrLoadSettings()
        {
            var path = SettingsPath;
            var options = AssetDatabase.LoadAssetAtPath<Configuration>(path);
            if (options == null)
            {
                Directory.CreateDirectory(Path.GetDirectoryName(path));

                options = CreateInstance<Configuration>();

                AssetDatabase.CreateAsset(options, path);
                AssetDatabase.SaveAssets();
            }
            return options;
        }

        private string GetRelativePath(string fromPath, string toPath)
        {   
            Uri fromUri = new Uri(fromPath);
            Uri toUri = new Uri(toPath);
            
            Uri relativeUri = fromUri.MakeRelativeUri(toUri);
            
            return Uri.UnescapeDataString(relativeUri.ToString());
        }
    }
}