using System;
using System.Reflection;

using Harmony;
// test
using Svelto.ECS;
using RobocraftX.Blocks;
using RobocraftX.Common;
using RobocraftX.SimulationModeState;

using GamecraftModdingAPI.Commands;
using GamecraftModdingAPI.Events;
using GamecraftModdingAPI.Utility;

namespace GamecraftModdingAPI.Tests
{
    // unused by design
    /// <summary>
    /// Modding API implemented as a standalone IPA Plugin.
    /// Ideally, GamecraftModdingAPI should be loaded by another mod; not itself
    /// </summary>
    public class GamecraftModdingAPIPluginTest
#if DEBUG
        : IllusionPlugin.IEnhancedPlugin
#endif
    {
        private static HarmonyInstance harmony { get; set; }

        public string[] Filter { get; } = new string[] { "Gamecraft", "GamecraftPreview" };

        public string Name { get; } = Assembly.GetExecutingAssembly().GetName().Name;

        public string Version { get; } = Assembly.GetExecutingAssembly().GetName().Version.ToString();

        public string HarmonyID { get; } = "org.git.exmods.modtainers.gamecraftmoddingapi";

        public void OnApplicationQuit()
        {
            GamecraftModdingAPI.Main.Shutdown();
        }

        public void OnApplicationStart()
        {
            GamecraftModdingAPI.Main.Init();
			// in case Steam is not installed/running
			// this will crash the game slightly later during startup
			//SteamInitPatch.ForcePassSteamCheck = true;
			// in case running in a VM
			//MinimumSpecsCheckPatch.ForcePassMinimumSpecCheck = true;
			// disable some Gamecraft analytics
			//AnalyticsDisablerPatch.DisableAnalytics = true;
			// disable background music
			Logging.MetaDebugLog("Audio Mixers: "+string.Join(",", AudioTools.GetMixers()));
			//AudioTools.SetVolume(0.0f, "Music"); // The game now sets this from settings again after this is called :(

            // debug/test handlers
            EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("App Inited event!"); }, () => { },
                EventType.ApplicationInitialized, "appinit API debug"));
            EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("Menu Activated event!"); },
                () => { Logging.Log("Menu Destroyed event!"); },
                EventType.Menu, "menuact API debug"));
            EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("Menu Switched To event!"); }, () => { },
                EventType.MenuSwitchedTo, "menuswitch API debug"));
            EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("Game Activated event!"); },
                () => { Logging.Log("Game Destroyed event!"); },
                EventType.Game, "gameact API debug"));
            EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("Game Reloaded event!"); }, () => { },
                EventType.GameReloaded, "gamerel API debug"));
            EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("Game Switched To event!"); }, () => { },
                EventType.GameSwitchedTo, "gameswitch API debug"));
			EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("Game Mode Simulation Switched To event!"); }, () => { },
			    EventType.SimulationSwitchedTo, "simulationswitch API debug"));
			EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("Game Mode Build Switched To event!"); }, () => { },
                EventType.BuildSwitchedTo, "buildswitch API debug"));

            // debug/test commands
			if (Dependency.Hell("ExtraCommands"))
			{
				CommandManager.AddCommand(new SimpleCustomCommandEngine(() => { UnityEngine.Application.Quit(); },
                "Exit", "Close Gamecraft without any prompts"));
                CommandManager.AddCommand(new SimpleCustomCommandEngine<float>((float d) => { UnityEngine.Camera.main.fieldOfView = d; },
                    "SetFOV", "Set the player camera's field of view"));
                CommandManager.AddCommand(new SimpleCustomCommandEngine<float, float, float>(
                    (x, y, z) => {
                        bool success = GamecraftModdingAPI.Blocks.Movement.MoveConnectedBlocks(
                            GamecraftModdingAPI.Blocks.BlockIdentifiers.LatestBlockID,
                            new Unity.Mathematics.float3(x, y, z));
                        if (!success)
                        {
                            GamecraftModdingAPI.Utility.Logging.CommandLogError("Blocks can only be moved in Build mode!");
                        }
                    }, "MoveLastBlock", "Move the most-recently-placed block, and any connected blocks by the given offset"));
                CommandManager.AddCommand(new SimpleCustomCommandEngine<float, float, float>(
                    (x, y, z) => { Blocks.Placement.PlaceBlock(Blocks.BlockIDs.AluminiumCube, new Unity.Mathematics.float3(x, y, z)); },
                    "PlaceAluminium", "Place a block of aluminium at the given coordinates"));
                Analytics.DeltaDNAHelper.PlayerLifetimeParameters plp = new Analytics.DeltaDNAHelper.PlayerLifetimeParameters();
                CommandManager.AddCommand(new SimpleCustomCommandEngine<string>(
                    (s) => { Analytics.DeltaDNAHelper.SendActionCompletedEvent(in plp, s.Replace(", ", " ")); },
                    "SendAnalyticsAction", "Send an analytics action"));
				System.Random random = new System.Random(); // for command below
				CommandManager.AddCommand(new SimpleCustomCommandEngine(
					() => { 
					    if (!GameState.IsSimulationMode())
					    {
							Logging.CommandLogError("You must be in simulation mode for this to work!");
							return;
					    }
					    Tasks.Repeatable task = new Tasks.Repeatable(() => {
    						    uint count = 0;
						        EGID[] eBlocks = Blocks.Signals.GetElectricBlocks();
                                for (uint i = 0u; i < eBlocks.Length; i++)
                                {
							        uint[] ids = Blocks.Signals.GetSignalIDs(eBlocks[i]);
                                    for (uint j = 0u; j < ids.Length; j++)
                                    {
								        Blocks.Signals.SetSignalByID(ids[j], (float)random.NextDouble());
                                        count++;
                                    }
                                }
                                Logging.MetaDebugLog($"Did the thing on {count} inputs");
					        },
					                                                 () => { return GameState.IsSimulationMode(); });
						Tasks.Scheduler.Schedule(task);
					}, "RandomizeSignalsInputs", "Do the thing"));
			}

            // dependency test
            if (Dependency.Hell("GamecraftScripting", new Version("0.0.1.0")))
			{
				Logging.LogWarning("You're in GamecraftScripting dependency hell");
			}
			else
			{
				Logging.Log("Compatible GamecraftScripting detected");
			}
        }

        public void OnFixedUpdate() { }

        public void OnLateUpdate() { }

        public void OnLevelWasInitialized(int level) { }

        public void OnLevelWasLoaded(int level) { }

        public void OnUpdate() { }
    }
}