// modules
using ModMenu;
using Func;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using FreezeThread;
using TelemetryWebpost;
using SixLabors.ImageSharp.Processing.Processors.Normalization;
using SixLabors.ImageSharp.Processing;

namespace ModMenu {
    public class ModMenuRequest {
        public string? action { get; set; }
        public string[]? settings { get; set; }
    }

    public class httpMenu {
        public static uint sessionId;
        public static List<GearQueueSlot> GearQueue = new List<GearQueueSlot>();
        public static uint Gender;
        public static uint Level;
        public static uint Cash;
        public static uint SeaSnails;
        public static uint HeadgearID;
        public static uint ClothesID;
        public static uint ShoesID;
        public static uint WeaponSetID;
        public static SessionData session = new SessionData();
        static WorkThread sessiondIdThread = new WorkThread(() => {
            Codes.forceSessiondId(sessionId);
        });
        static WorkThread WriteGear = new WorkThread(() => {
            SaveEditor.WriteGearQueue();
        });
        static WorkThread ChangeGender = new WorkThread(() => {
            SaveEditor.ChangeGender(Gender);
        });
        static WorkThread ChangeLevel = new WorkThread(() => {
            SaveEditor.ChangeLevel(Level);
        });
        static WorkThread ChangeCash = new WorkThread(() => {
            SaveEditor.ChangeCash(Cash);
        });
        static WorkThread ChangeSeaSnails = new WorkThread(() => {
            SaveEditor.ChangeSeaSnails(SeaSnails);
        });
        static WorkThread TelemetryThread = new WorkThread(() => {
            Thread.Sleep(5000);
            SplatTelemetry.SendTelemetry();
        });
        static WorkThread HeadgearChangeThread = new WorkThread(() => {
            SaveEditor.ChangeEquippedHeadgear(HeadgearID);
        });
        static WorkThread ClothesChangeThread = new WorkThread(() => {
            SaveEditor.ChangeEquippedClothes(ClothesID);
        });
        static WorkThread ShoesChangeThread = new WorkThread(() => {
            SaveEditor.ChangeEquippedShoes(ShoesID);
        });
        static WorkThread WeaponChangeThread = new WorkThread(() => {
            SaveEditor.ChangeEquippedWeapon(WeaponSetID);
        });

        public static string RunCode(ModMenuRequest data) {
            if (data?.action == null) return "0";

            switch (data.action) {
                case "cbase":
                    return $"Cemu Base: 0x{Program.cbase:X} (0x{Program.cbaseCorrected:X})<br><br>Total Wins: {Codes.TotalWins()}<br>Total Losses: {Codes.TotalLoss()}<br>Equipped Headgear: {Codes.EquippedHeadgear()}<br>Equipped Clothes: {Codes.EquippedClothes()}<br>Equipped Shoes: {Codes.EquippedShoes()}<br>Equipped Weapon: {Codes.EquippedWep()}<br><br>Thread Status:<br>- Write Gear: {WriteGear.Status.ToString()}<br>- Telemetry: {TelemetryThread.Status.ToString()}<br>- Change Gender: {ChangeGender.Status.ToString()}<br>- Change Level: {ChangeLevel.Status.ToString()}<br>- Change Cash: {ChangeCash.Status.ToString()}<br>- Change Sea Snails: {ChangeSeaSnails.Status.ToString()}<br>- Change Headgear: {HeadgearChangeThread.Status.ToString()}<br>- Change Clothes: {ClothesChangeThread.Status.ToString()}<br>- Change Shoes: {ShoesChangeThread.Status.ToString()}<br>- Change Weapon: {WeaponChangeThread.Status.ToString()}";

                case "sessiondata":
                    return Codes.GetSessionData();

                case "namechange":
                    if (data.settings?.Length > 0) Codes.NameChanger(data.settings[0]);
                    return "1";

                case "sessionid":
                    if (data.settings?.Length > 0) {
                        sessionId = (uint)Int32.Parse(data.settings[0]);
                        HandleThread(sessiondIdThread);
                    }
                    return "1";

                case "faceimgtga":
                    Codes.faceimgtga(Int32.Parse(data.settings[0]));
                    return "1";

                case "OSType":
                    return Program.OsType.ToString();

                case "FetchGear":
                    return SaveEditor.FetchAllGear();

                case "WriteToGearQueue":
                    SaveEditor.QueueGearSlot(UInt32.Parse(data.settings[0]), data.settings[1], UInt32.Parse(data.settings[2]), UInt32.Parse(data.settings[3]), UInt32.Parse(data.settings[4]), UInt32.Parse(data.settings[5]));
                    return "1";

                case "WriteGearQueue":
                    if (WriteGear.Status == WorkThread.ThreadStatus.Stopped) {
                        WriteGear.Start();
                    } else if (WriteGear.Status == WorkThread.ThreadStatus.Running) {
                        WriteGear.Stop();
                        GearQueue = new List<GearQueueSlot>();
                        GearQueue.Clear();
                    }
                    return "1";

                case "ChangeGender":
                    Gender = UInt32.Parse(data.settings[0]);
                    HandleThread(ChangeGender);
                    return "1";

                case "ChangeLevel":
                    try {
                        Level = UInt32.Parse(data.settings[0]);
                    } catch {
                        Level = 0;
                    }
                    HandleThread(ChangeLevel);
                    return "1";

                case "ChangeCash":
                    try {
                        Cash = UInt32.Parse(data.settings[0]);
                    } catch {
                        Cash = 0;
                    }
                    HandleThread(ChangeCash);
                    return "1";

                case "ChangeSeaSnails":
                    try {
                        SeaSnails = UInt32.Parse(data.settings[0]);
                    } catch {
                        SeaSnails = 0;
                    }
                    HandleThread(ChangeSeaSnails);
                    return "1";

                case "DisconnectLobby":
                    Codes.DisconnectFromLobby();
                    return "1";

                case "Webpost":
                    HandleThread(TelemetryThread);
                    return "1";

                case "HeadgearChange":
                    HeadgearID = UInt32.Parse(data.settings[0]);
                    HandleThread(HeadgearChangeThread);
                    return "1";

                case "HeadgearChangeApply":
                    HeadgearID = UInt32.Parse(data.settings[0]);
                    return "1";

                case "ClothesChange":
                    ClothesID = UInt32.Parse(data.settings[0]);
                    HandleThread(ClothesChangeThread);
                    return "1";

                case "ClothesChangeApply":
                    ClothesID = UInt32.Parse(data.settings[0]);
                    return "1";

                case "ShoesChange":
                    ShoesID = UInt32.Parse(data.settings[0]);
                    HandleThread(ShoesChangeThread);
                    return "1";

                case "ShoesChangeApply":
                    ShoesID = UInt32.Parse(data.settings[0]);
                    return "1";

                case "WepChange":
                    WeaponSetID = UInt32.Parse(data.settings[0]);
                    HandleThread(WeaponChangeThread);
                    return "1";

                case "WepChangeApply":
                    WeaponSetID = UInt32.Parse(data.settings[0]);
                    return "1";

                case "AllEquipment":
                    string headgearID = Codes.EquippedHeadgear();
                    string clothesID = Codes.EquippedClothes();
                    string shoesID = Codes.EquippedShoes();
                    string weaponId = Codes.EquippedWep();
                    return $"{{\"EquippedHeadgearId\": \"{headgearID}\", \"EquippedClothesId\": \"{clothesID}\", \"EquippedShoesId\": \"{shoesID}\", \"EquippedWepId\": \"{weaponId}\"}}";

                default:
                    return "Not Found";
            }
        }

        private static void HandleThread(WorkThread thread) {
            if (thread.Status == WorkThread.ThreadStatus.Stopped) {
                thread.Start();
            } else if (thread.Status == WorkThread.ThreadStatus.Running) {
                thread.Pause();
            } else if (thread.Status == WorkThread.ThreadStatus.Paused) {
                thread.Resume();
            } else {
                thread.Pause();
            }
        }
    }
}
