// Copyright (c) Wojciech Figat. All rights reserved.

using System.Collections.Generic;
using System.IO;
using Flax.Build;

namespace Flax.Deps.Dependencies
{
    /// <summary>
    /// Multi-channel signed distance field generator. https://github.com/Chlumsky/msdfgen
    /// </summary>
    /// <seealso cref="Flax.Deps.Dependency" />
    class msdfgen : Dependency
    {
        /// <inheritdoc />
        public override TargetPlatform[] Platforms
        {
            get
            {
                switch (BuildPlatform)
                {
                case TargetPlatform.Windows:
                    return new[]
                    {
                        TargetPlatform.Windows,
                        TargetPlatform.Android,
                        TargetPlatform.XboxOne,
                        TargetPlatform.XboxScarlett,
                        TargetPlatform.Switch,
                        TargetPlatform.PS4,
                        TargetPlatform.PS5,
                        TargetPlatform.Web,
                    };
                case TargetPlatform.Linux:
                    return new[]
                    {
                        TargetPlatform.Linux,
                    };
                case TargetPlatform.Mac:
                    return new[]
                    {
                        TargetPlatform.Mac,
                        TargetPlatform.iOS,
                    };
                default: return new TargetPlatform[0];
                }
            }
        }

        /// <inheritdoc />
        public override TargetArchitecture[] Architectures
        {
            get
            {
                switch (BuildPlatform)
                {
                case TargetPlatform.Windows:
                    return new[]
                    {
                        TargetArchitecture.x86,
                        TargetArchitecture.x64,
                        TargetArchitecture.ARM64,
                    };
                case TargetPlatform.Linux:
                    return new[]
                    {
                        TargetArchitecture.x64,
                        //TargetArchitecture.ARM64,
                    };
                case TargetPlatform.Mac:
                    return new[]
                    {
                        TargetArchitecture.x64,
                        TargetArchitecture.ARM64,
                    };
                default: return new TargetArchitecture[0];
                }
            }
        }

        /// <inheritdoc />
        public override void Build(BuildOptions options)
        {
            var root = options.IntermediateFolder;
            var configuration = "Release";
            string includeDir = null;
            var filesToKeep = new[]
            {
                "msdfgen.Build.cs",
            };
            var args = new string[]
            {
                "-DMSDFGEN_BUILD_STANDALONE=OFF",
                "-DMSDFGEN_USE_VCPKG=OFF",
                "-DMSDFGEN_CORE_ONLY=ON",
                "-DMSDFGEN_DYNAMIC_RUNTIME=ON",
                "-DMSDFGEN_USE_SKIA=OFF",
                "-DMSDFGEN_INSTALL=ON",
                "-DMSDFGEN_USE_SKIA=OFF",
                "-DMSDFGEN_DISABLE_SVG=ON",
                "-DMSDFGEN_DISABLE_PNG=ON",
                "-DMSDFGEN_DYNAMIC_RUNTIME=ON",
                "-DBUILD_SHARED_LIBS=OFF",
            };

            // Get the source
            var commit = "1874bcf7d9624ccc85b4bc9a85d78116f690f35b"; // Version 1.13
            CloneGitRepoSingleBranch(root, "https://github.com/Chlumsky/msdfgen.git", "master", commit);

            foreach (var platform in options.Platforms)
            {
                foreach (var architecture in options.Architectures)
                {
                    BuildStarted(platform, architecture);

                    var isMSVC = Platform.GetPlatform(platform, true) is Build.Platforms.WindowsPlatformBase;
                    var buildDir = Path.Combine(root, "build-" + architecture);
                    var installDir = Path.Combine(root, "install-" + architecture);
                    var depsFolder = GetThirdPartyFolder(options, platform, architecture);
                    includeDir = Path.Combine(installDir, "include");
                    SetupDirectory(buildDir, true);
                    File.Delete(Path.Combine(root, "CMakeCache.txt"));

                    var envVars = new Dictionary<string, string>
                    {
                        { "CXXFLAGS", isMSVC ? "/EH- /GR-" : "-fno-exceptions -fno-rtti" }, // Disable exceptions and RTTI
                        { "CMAKE_BUILD_PARALLEL_LEVEL", CmakeBuildParallel },
                    };
                    var libName = "libmsdfgen-core.a";
                    var cmakeArgs = string.Join(" ", args);
                    switch (platform)
                    {
                    case TargetPlatform.Windows:
                    case TargetPlatform.XboxOne:
                    case TargetPlatform.XboxScarlett:
                        libName = "msdfgen-core.lib";
                        break;
                    case TargetPlatform.Linux:
                        envVars["CC"] = "clang-" + LinuxConfiguration.ClangMinVer;
                        envVars["CC_FOR_BUILD"] = "clang-" + LinuxConfiguration.ClangMinVer;
                        envVars["CXX"] = "clang++-" + LinuxConfiguration.ClangMinVer;
                        cmakeArgs += " -DCMAKE_POSITION_INDEPENDENT_CODE=ON";
                        break;
                    }

                    RunCmake(root, platform, architecture, $"-B\"{buildDir}\" -Wno-dev " + cmakeArgs, envVars);
                    BuildCmake(buildDir);
                    Utilities.Run("cmake", $"--install {buildDir} --prefix {installDir} --config {configuration}", null, root, Utilities.RunOptions.DefaultTool);
                    Utilities.FileCopy(Path.Combine(installDir, "lib", libName), Path.Combine(depsFolder, libName));
                }
            }

            // Backup files
            var dstIncludePath = Path.Combine(options.ThirdPartyFolder, "msdfgen");
            foreach (var filename in filesToKeep)
            {
                var src = Path.Combine(dstIncludePath, filename);
                var dst = Path.Combine(options.IntermediateFolder, filename + ".tmp");
                Utilities.FileCopy(src, dst);
            }

            // Deploy header files and license
            SetupDirectory(dstIncludePath, true);
            Utilities.FileCopy(Path.Combine(root, "LICENSE.txt"), Path.Combine(dstIncludePath, "LICENSE.txt"));
            Utilities.DirectoryCopy(includeDir, dstIncludePath, true, true);
            foreach (var filename in filesToKeep)
            {
                var src = Path.Combine(options.IntermediateFolder, filename + ".tmp");
                var dst = Path.Combine(dstIncludePath, filename);
                Utilities.FileCopy(src, dst);
            }
        }
    }
}
