using System.Diagnostics;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;

public class HookahAssetBuilder
{
    static readonly string ModManagerProfilesPath =
        @"C:\Users\user\AppData\Roaming\com.kesomannen.gale\lethal-company\profiles";
    static readonly string ModPackProfileName = "HookahPlace Test";
    static readonly string ModPackModName = "HookahPlace-DEV";
    static readonly string ModPackProfilePath = $@"{ModManagerProfilesPath}/{ModPackProfileName}";
    static readonly string ModPackHookahPlacePath = @$"{ModPackProfilePath}/BepInEx/plugins/{ModPackModName}";

    static readonly string ModProjectPath = @"D:\Code\LethalCompany\Mods\HookahPlace";
    static readonly string DllName = "Ratijas.HookahPlace.dll";
    static readonly string DllSourcePath = $@"{ModProjectPath}/HookahPlace/bin/Debug/netstandard2.1/{DllName}";
    static readonly string[] DllDestinationPaths = new string[]
    {
        // relative to Unity project
        $@"Assets/LethalCompany/Mods/plugins/Dependencies/{ModPackModName}",
        ModPackHookahPlacePath,
    };

    static readonly string AssetBundlesPath = "Assets/LethalCompany/Mods/plugins/HookahPlace/AssetBundles";
    static readonly string[] AssetBundlesDestinationPaths = new string[]
    {
        @$"{ModPackHookahPlacePath}/Assets",
        @$"{ModProjectPath}/HookahPlace/res",
    };

    public static BuildAssetBundlesParameters GetBuildAssetBundlesParameters()
    {
        var assetBundleDefinitions = new AssetBundleBuild[]
        {
            new AssetBundleBuild()
            {
                assetBundleName = "hookahplaceasset",
                assetNames = new string[]
                {
                    "Assets/LethalCompany/Mods/plugins/HookahPlace/HookahContentContainer.asset",
                }
            },
            new AssetBundleBuild()
            {
                assetBundleName = "hookahunlockableassets",
                assetNames = new string[]
                {
                    "Assets/LethalCompany/Mods/plugins/HookahPlace/Content/Unlockables",
                }
            },
        };
        var buildParameters = new BuildAssetBundlesParameters()
        {
            outputPath = AssetBundlesPath,
            options = BuildAssetBundleOptions.ChunkBasedCompression,
            bundleDefinitions = assetBundleDefinitions
        };
        return buildParameters;
    }

    [MenuItem("HookahPlace/All")]
    public static void DoAll()
    {
        CompileScripts();
        BuildAssetBundles();
        InstallAssetBundles();
        LaunchGame();
    }

    [MenuItem("HookahPlace/1. Compile Scripts")]
    public static void CompileScripts()
    {
        var psi = new ProcessStartInfo
        {
            FileName = "dotnet",
            Arguments = "build",
            UseShellExecute = false,
            WorkingDirectory = ModProjectPath,
        };

        var proc = Process.Start(psi);
        proc.WaitForExit();

        if (proc.ExitCode != 0)
        {
            UnityEngine.Debug.Log($"Process exited with non-zero code: {proc.ExitCode}");
            // proc.StandardOutput
            return;
        }

        foreach (var destinationPath in DllDestinationPaths)
        {
            Directory.CreateDirectory(destinationPath);

            var sourceFileName = DllSourcePath;
            var destFileName = $"{destinationPath}/{DllName}";
            FileCopy(sourceFileName, destFileName);
        }
    }

    [MenuItem("HookahPlace/2. Build Asset Bundles")]
    public static void BuildAssetBundles()
    {
        UnityEngine.Debug.Log("Building asset bundles for HookahPlace...");

        var buildParameters = GetBuildAssetBundlesParameters();
        Directory.CreateDirectory(buildParameters.outputPath);
        AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(buildParameters);

        if (manifest != null)
        {
            foreach(var bundleName in manifest.GetAllAssetBundles())
            {
                string projectRelativePath = buildParameters.outputPath + "/" + bundleName;
                UnityEngine.Debug.Log($"Size of AssetBundle {projectRelativePath} is {new FileInfo(projectRelativePath).Length}");
            }
        }
        else
        {
            UnityEngine.Debug.Log("Build failed, see Console and Editor log for details");
        }

        if (Application.isBatchMode)
        {
            EditorApplication.Exit(0);
        }
    }

    [MenuItem("HookahPlace/3. Install Asset Bundles")]
    public static void InstallAssetBundles()
    {
        UnityEngine.Debug.Log("Installing asset bundles for HookahPlace...");

        var buildParameters = GetBuildAssetBundlesParameters();

        foreach (var destinationPath in AssetBundlesDestinationPaths)
        {
            Directory.CreateDirectory(destinationPath);

            foreach (var bundle in buildParameters.bundleDefinitions)
            {
                var name =  bundle.assetBundleName;
                var sourceFileName = $"{buildParameters.outputPath}/{name}";
                var destFileName = $"{destinationPath}/{name}";
                FileCopy(sourceFileName, destFileName);
            }
        }
    }

    [MenuItem("HookahPlace/4. Launch Game")]
    public static void LaunchGame()
    {
        UnityEngine.Debug.Log($"Launching Gale profile with profile '{ModPackProfileName}'...");

        string BepInExPreloaderDllPath = $@"{ModPackProfilePath}/BepInEx/core/BepInEx.Preloader.dll";

        string[] args = new string[]
        {
            @"C:\Program Files (x86)\Steam\steam.exe",
            "-applaunch",
            "1966720",
            "--doorstop-enabled",
            "true",
            "--doorstop-target-assembly",
            BepInExPreloaderDllPath,
        };

        var psi = new ProcessStartInfo
        {
            FileName = args[0],
            Arguments = string.Join(" ", args.Skip(1).Select(QuoteArgument)),
            UseShellExecute = false,
        };

        Process.Start(psi);

        GUIUtility.systemCopyBuffer = "hookah";
    }

    static void FileCopy(string sourceFileName, string destFileName)
    {
        UnityEngine.Debug.Log($"File.Copy {sourceFileName} => {destFileName}");
        File.Copy(sourceFileName, destFileName, overwrite: true);
    }

    static string QuoteArgument(string arg)
    {
        if (string.IsNullOrEmpty(arg))
            return "\"\"";

        if (arg.IndexOfAny(new char[] { ' ', '\t', '"' }) == -1)
            return arg;

        return "\"" + arg.Replace("\"", "\\\"") + "\"";
    }
}
