﻿#region Header

// Copyright (c) 2021-2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.

#endregion

using System.IO;
using UnityEditor;
using UnityEngine;
using IniParser;
using IniParser.Model;
using System.Runtime.InteropServices;

namespace BlackBox
{
    public sealed class ConfigurationWindow : EditorWindow
    {
        #region Static or Const Fields

        private static ConfigurationWindow windowInstance_;

        public const string RESOURCES = "Resources";
        public const string BLACKBOX = "BlackBox";
        public const string WEB_CONFIG = "webconfig";
        public const string CONFIG_TRUE = "1";
        public const string CONFIG_FALSE = "0";
        // public const string DEFAULT_CONFIG = "DefaultConfig";

        #endregion Static or Const Fields

        #region Static Methods

        /// <summary>
        ///     Menu callback for opening the Window
        /// </summary>
        public static void ShowSceneLoader()
        {
            if (windowInstance_ != null)
            {
                windowInstance_.Close();
                windowInstance_ = null;
            }
            else
            {
                windowInstance_ = (ConfigurationWindow)GetWindow(typeof(ConfigurationWindow), true, "BlackBox");
                windowInstance_.Initialize();
                windowInstance_.Show();
            }
        }

        #endregion Static Methods

        #region Properties | Fields

        private Texture2D Logo { get; set; }

        private Rect logoRect_;

        #endregion Properties | Fields

        #region Setup

        public void Initialize()
        {
            Logo = Resources.Load<Texture2D>("logo");
            logoRect_ = new Rect((position.width - 300) / 2, 10, 300, 86);
        }

        #endregion

        #region Unity Event Methods

        private void OnGUI()
        {
            // Draw logo
            logoRect_.x = (position.width - 300) / 2;
            GUI.DrawTexture(logoRect_, Logo);

            EditorGUILayout.BeginVertical();
            EditorGUILayout.Space(100);

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Namespace");
            BlackBoxConfig.Instance.Namespace = EditorGUILayout.TextField(BlackBoxConfig.Instance.Namespace);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("API Key");
            BlackBoxConfig.Instance.ApiKey = EditorGUILayout.TextField(BlackBoxConfig.Instance.ApiKey);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Game Version Id");
            BlackBoxConfig.Instance.GameVersionId = EditorGUILayout.TextField(BlackBoxConfig.Instance.GameVersionId);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Build Id");
            BlackBoxConfig.Instance.BuildId = EditorGUILayout.TextField(BlackBoxConfig.Instance.BuildId);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Base URL");
            BlackBoxConfig.Instance.BaseUrl = EditorGUILayout.TextField(BlackBoxConfig.Instance.BaseUrl);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Is Auto Initialize");
            BlackBoxConfig.Instance.AutoInitialize = EditorGUILayout.Toggle(BlackBoxConfig.Instance.AutoInitialize);
            EditorGUILayout.EndHorizontal();
#if UNITY_STANDALONE_WIN
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Enable Logs");
            BlackBoxConfig.Instance.EnableLogs = EditorGUILayout.Toggle(BlackBoxConfig.Instance.EnableLogs);
            EditorGUILayout.EndHorizontal();
#endif

#if UNITY_STANDALONE_WIN
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Crash Config Option");
            BlackBoxConfig.Instance.ConfigOption = (ConfigOption)EditorGUILayout.EnumPopup(BlackBoxConfig.Instance.ConfigOption);
            EditorGUILayout.EndHorizontal();
#endif

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Enable Basic Profiling");
            EditorGUI.BeginDisabledGroup(true ? BlackBoxConfig.Instance.ConfigOption == ConfigOption.Web : false);
            BlackBoxConfig.Instance.EnableBasicProfiling = EditorGUILayout.Toggle(BlackBoxConfig.Instance.EnableBasicProfiling);
            EditorGUI.EndDisabledGroup();
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Enable Crash Reporter");
            EditorGUI.BeginDisabledGroup(true ? BlackBoxConfig.Instance.ConfigOption == ConfigOption.Web : false);
            BlackBoxConfig.Instance.EnableCrashReporter = EditorGUILayout.Toggle(BlackBoxConfig.Instance.EnableCrashReporter);
            EditorGUI.EndDisabledGroup();
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Store Hardware Information");
            EditorGUI.BeginDisabledGroup(true ? BlackBoxConfig.Instance.ConfigOption == ConfigOption.Web : false);
            BlackBoxConfig.Instance.StoreHardwareInformation = EditorGUILayout.Toggle(BlackBoxConfig.Instance.StoreHardwareInformation);
            EditorGUI.EndDisabledGroup();
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Debug Platform");
            BlackBoxConfig.Instance.Platform = (Platform)EditorGUILayout.EnumPopup(BlackBoxConfig.Instance.Platform);
            EditorGUILayout.EndHorizontal();

#if UNITY_STANDALONE_WIN
            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Enable Issue Reporter");
            BlackBoxConfig.Instance.EnableIssueReporter = EditorGUILayout.Toggle(BlackBoxConfig.Instance.EnableIssueReporter);
            EditorGUILayout.EndHorizontal();

            EditorGUI.BeginDisabledGroup(BlackBoxConfig.Instance.EnableIssueReporter == false);
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Include Log in Issue Reporter");
            BlackBoxConfig.Instance.IncludeGameLogInIssueReport = EditorGUILayout.Toggle(BlackBoxConfig.Instance.IncludeGameLogInIssueReport);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Issue Reporter HotKey");
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.Space(10, false);

            GUI.SetNextControlName("IssueReporterKeyInputField");
            string IssueReporterKeyStr = EditorGUILayout.TextField("Key :", BlackBoxConfig.Instance.IssueReporterKey.Key.ToString(), GUILayout.MaxWidth(300));

            KeyCode IssueReporterKey = BlackBoxConfig.Instance.IssueReporterKey.Key;
            bool bUpdateKey = false;

            if (GUI.GetNameOfFocusedControl() == "IssueReporterKeyInputField")
            {
                Event evt = Event.current;
                if (evt.isKey)
                {
                    IssueReporterKey = evt.keyCode;
                    bUpdateKey = true;
                    GUI.FocusControl(null);
                }
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.Space(10, false);
            bool bAlt = EditorGUILayout.Toggle("Alt :", BlackBoxConfig.Instance.IssueReporterKey.bAlt, GUILayout.ExpandWidth(false));
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.Space(10, false);
            bool bCtrl = EditorGUILayout.Toggle("Ctrl :", BlackBoxConfig.Instance.IssueReporterKey.bCtrl, GUILayout.ExpandWidth(false));
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.Space(10, false);
            bool bShift = EditorGUILayout.Toggle("Shift :", BlackBoxConfig.Instance.IssueReporterKey.bShift, GUILayout.ExpandWidth(false));
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.Space(10, false);
            bool bCmd = EditorGUILayout.Toggle("Cmd :", BlackBoxConfig.Instance.IssueReporterKey.bCmd, GUILayout.ExpandWidth(false));

            BlackBoxConfig.Instance.IssueReporterKey.Setup(IssueReporterKey, bAlt, bCtrl, bShift, bCmd);
            if (bUpdateKey)
            {
                Repaint();
            }
            EditorGUILayout.EndHorizontal();

            EditorGUI.EndDisabledGroup();
#endif

            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button("Read config from BlackBox.ini"))
            {
                var parser = new FileIniDataParser();
                var blackboxCliConfig = Path.Combine(Application.streamingAssetsPath, "BlackBox", "BlackBox.ini");
                var blackboxCliUserConfig = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile), ".blackbox", "config.ini");

                if (!File.Exists(blackboxCliUserConfig) && !File.Exists(blackboxCliUserConfig))
                {
                    Logger.LogWarning($"No '{blackboxCliConfig}' and '{blackboxCliUserConfig}' file to read from.");
                }
                else
                {
                    BlackBoxConfig.LoadBlackBoxConfig(BlackBoxConfig.Instance);
                    Logger.Log($"Read config from '{blackboxCliUserConfig}' and '{blackboxCliConfig}' file");
                }
            }

            if (GUILayout.Button("Save config"))
            {
                var config = BlackBoxConfig.Instance;

                // Update BlackBox.ini file
                if (!File.Exists(PluginManager.GetConfigPath()))
                {
                    File.WriteAllText(PluginManager.GetConfigPath(), "");
                }
                Logger.Log("Config INI File: " + PluginManager.GetConfigPath());

                var parser = new FileIniDataParser();
                IniData configData = new IniData();
                configData = parser.ReadFile(PluginManager.GetConfigPath());
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.NAMESPACE_FIELD] = config.Namespace;
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.API_KEY_FIELD] = config.ApiKey;
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.GAME_VERSION_ID_FIELD] = config.GameVersionId;
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.BUILD_ID_FIELD] = config.BuildId;
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.BASE_URL_FIELD] = config.BaseUrl;
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.ENABLE_BASIC_PROFILING] = config.EnableBasicProfiling.ToString();
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.ENABLE_CRASH_REPORTER] = config.EnableCrashReporter.ToString();
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.STORE_HARDWARE_INFO] = config.StoreHardwareInformation.ToString();
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.ENABLE_LOGS] = config.EnableLogs.ToString();
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.IS_AUTO_INITIALIZE] = config.AutoInitialize.ToString();
#if UNITY_STANDALONE_WIN
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.ISSUE_REPORTER_KEY_FIELD] = config.IssueReporterKey.Serialize();
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.ENABLE_ISSUE_REPORTER_FIELD] = config.EnableIssueReporter.ToString();
                configData[ConfigIniTemplate.BLACKBOX_SETTINGS][ConfigIniTemplate.INCLUDE_GAME_LOG_IN_ISSUE_REPORT_FIELD] = config.IncludeGameLogInIssueReport.ToString();

                string d = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "/BlackBoxHelper");
                Logger.Log("Writing Helper log: " + d);
                string BlackBoxAlternativeLog = Path.Combine(d, "/helper_1.log");
                Logger.Log("Writing Helper log: " + BlackBoxAlternativeLog);

                // System.IO.Directory.CreateDirectory(d);
                // string BlackBoxAlternativeLog = Path.Combine(d, "/helper_1.log");
#endif

                Logger.Log("Writing INI File: " + PluginManager.GetConfigPath());
                parser.WriteFile(PluginManager.GetConfigPath(), configData);

#if UNITY_STANDALONE_WIN
                if (BlackBoxConfig.Instance.ConfigOption == ConfigOption.Web)
                {
                    Logger.Log("Set Crash Config based on web settings");
                    PluginAPI.bbx_local_config_set_enable_basic_profiling(WEB_CONFIG);
                    PluginAPI.bbx_local_config_set_enable_crash_reporter(WEB_CONFIG);
                    PluginAPI.bbx_local_config_set_store_dxdiag(WEB_CONFIG);
                    PluginAPI.bbx_local_config_set_store_crash_video(WEB_CONFIG);
                }
                else if (BlackBoxConfig.Instance.ConfigOption == ConfigOption.Local)
                {
                    PluginAPI.bbx_local_config_set_enable_basic_profiling(BlackBoxConfig.Instance.EnableBasicProfiling ? CONFIG_TRUE : CONFIG_FALSE);
                    PluginAPI.bbx_local_config_set_enable_crash_reporter(BlackBoxConfig.Instance.EnableCrashReporter ? CONFIG_TRUE : CONFIG_FALSE);
                    PluginAPI.bbx_local_config_set_store_dxdiag(BlackBoxConfig.Instance.StoreHardwareInformation ? CONFIG_TRUE : CONFIG_FALSE);
                    PluginAPI.bbx_local_config_set_store_crash_video(BlackBoxConfig.Instance.StoreVideo ? CONFIG_TRUE : CONFIG_FALSE);
                    Logger.Log("Set Crash Config based on local settings");
                    PluginAPI.blackbox_save_local_config(Application.productName);
                }
                //PluginAPI.bbx_config_set_blackbox_helper_alternative_path(BlackBoxAlternativeLog);
                PluginAPI.bbx_config_set_issue_reporter_hotkey(BlackBoxConfig.Instance.IssueReporterKey.Serialize());
#endif
                config.SaveConfigAsset();

                Logger.Log("New configuration is saved");
            }
            EditorGUILayout.EndHorizontal();
        }

        private void OnDestroy()
        {
            windowInstance_ = null;
        }

        #endregion Unity Event Methods
    }
}
