using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using static DSPRE.DSUtils;
using static DSPRE.RomInfo;

namespace DSPRE {
    public static class OverlayUtils {
        public static class OverlayTable {
            private const int ENTRY_LEN = 32;

            /**
            * Only checks if the overlay is CONFIGURED as compressed
            **/
            public static bool IsDefaultCompressed(int ovNumber) {
                using (DSUtils.EasyReader f = new EasyReader(RomInfo.overlayTablePath, ovNumber * ENTRY_LEN + 31)) {
                    return (f.ReadByte() & 1) == 1;
                }
            }
            public static void SetDefaultCompressed(int ovNumber, bool compressStatus) {
                DSUtils.WriteToFile(RomInfo.overlayTablePath, new byte[] { compressStatus ? (byte)1 : (byte)0 }, (uint)(ovNumber * ENTRY_LEN + 31)); //overlayNumber * size of entry + offset
            }

            public static uint GetRAMAddress(int ovNumber) {
                using (DSUtils.EasyReader f = new EasyReader(RomInfo.overlayTablePath, ovNumber * ENTRY_LEN + 4)) {
                    return f.ReadUInt32();
                }
            }
            public static uint GetUncompressedSize(int ovNumber) {
                using (DSUtils.EasyReader f = new EasyReader(RomInfo.overlayTablePath, ovNumber * ENTRY_LEN + 8)) {
                    return f.ReadUInt32();
                }
            }

            /**
            * Gets number of overlays
            **/
            public static int GetNumberOfOverlays() {
                using (FileStream fileStream = File.OpenRead(RomInfo.overlayTablePath))
                {
                    // Get the length of the file in bytes
                    return (int)(fileStream.Length / ENTRY_LEN);
                }
            }
        }


        public static string GetPath(int overlayNumber) {
            return $"{workDir}overlay\\overlay_{overlayNumber:D4}.bin";
        }
       
        /**
         * Checks the actual size of the overlay file
         **/
        public static bool IsCompressed(int ovNumber) {
            return (new FileInfo(GetPath(ovNumber)).Length < OverlayTable.GetUncompressedSize(ovNumber));
        }

        public static void RestoreFromCompressedBackup(int overlayNumber, bool eventEditorIsReady) {
            String overlayFilePath = GetPath(overlayNumber);

            if (File.Exists(overlayFilePath + DSUtils.backupSuffix)) {
                if (new FileInfo(overlayFilePath).Length <= new FileInfo(overlayFilePath + DSUtils.backupSuffix).Length) { //if overlay is bigger than its backup
                    AppLogger.Info($"Overlay {overlayNumber} is already compressed.");
                    return;
                } else {
                    File.Delete(overlayFilePath);
                    File.Move(overlayFilePath + DSUtils.backupSuffix, overlayFilePath);
                }
            } else {
                string msg = $"Overlay File {overlayFilePath}{DSUtils.backupSuffix} couldn't be found and restored.";
                AppLogger.Debug(msg);

                if (eventEditorIsReady) {
                    MessageBox.Show(msg, "Can't restore overlay from backup", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        public static int Compress(int overlayNumber) {
            string overlayFilePath = GetPath(overlayNumber);

            if (!File.Exists(overlayFilePath)) {
                MessageBox.Show("Overlay to decompress #" + overlayNumber + " doesn't exist",
                    "Overlay not found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return ERR_OVERLAY_NOTFOUND;
            }

            Process compress = new Process();
            compress.StartInfo.FileName = @"Tools\blz.exe";
            compress.StartInfo.Arguments = "-en " + '"' + overlayFilePath + '"';
            Application.DoEvents();
            compress.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            compress.StartInfo.CreateNoWindow = true;
            compress.Start();
            compress.WaitForExit();
            return compress.ExitCode;
        }

        public static int Decompress(string overlayFilePath, bool makeBackup = true) {
            if (!File.Exists(overlayFilePath)) {
                MessageBox.Show($"File to decompress \"{overlayFilePath}\" doesn't exist",
                    "Overlay not found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return ERR_OVERLAY_NOTFOUND;
            }

            if (makeBackup) {
                if (File.Exists(overlayFilePath + backupSuffix)) {
                    File.Delete(overlayFilePath + backupSuffix);
                }
                File.Copy(overlayFilePath, overlayFilePath + backupSuffix);
            }

            Process decompress = DSUtils.CreateDecompressProcess(overlayFilePath);
            decompress.Start();
            decompress.WaitForExit();
            return decompress.ExitCode;
        }
        public static int Decompress(int overlayNumber, bool makeBackup = true) {
            return Decompress(GetPath(overlayNumber), makeBackup);
        }

    }
}