/**
 * Copyright 2022-2025 Theai, Inc. dba Inworld AI
 */

#define CUDA

using System;
using System.IO;
using UnrealBuildTool;

public class InworldRuntimeLibrary : ModuleRules
{
    private string ThirdPartyLibrariesDirectory
    {
        get
        {
            return Path.Combine(ModuleDirectory, Target.Platform.ToString());
        }
    }

    private string PluginBinariesDirectory
    {
        get
        {
            return Path.Combine("$(PluginDir)", "Binaries", Target.Platform.ToString());
        }
    }

    private string ThirdPartyIncludesDirectory
    {
        get
        {
            return Path.Combine(ModuleDirectory, "Public");
        }
    }

    private string PluginExtrasDirectory
    {
        get
        {
            return Path.Combine(PluginDirectory, "Extras/...");
        }
    }

    public InworldRuntimeLibrary(ReadOnlyTargetRules Target) : base(Target)
	{
		Type = ModuleType.External;

        PublicIncludePaths.Add(ThirdPartyIncludesDirectory);

        if (!TargetPlatformSupported)
        {
            return;
        }

        PublicDefinitions.Add("INWORLD_IMPLEMENTATION=1");
        RuntimeDependencies.Add(PluginExtrasDirectory, StagedFileType.NonUFS);

        if (Target.Platform == UnrealTargetPlatform.Win64)
        {
            PublicAdditionalLibraries.Add(Path.Combine(ModuleDirectory, Target.Platform.ToString(), "inworld.if.lib"));
            PublicDelayLoadDLLs.Add("inworld.dll");

            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "inworld.dll"), Path.Combine(ThirdPartyLibrariesDirectory, "inworld.dll"));
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "onnxruntime.dll"), Path.Combine(ThirdPartyLibrariesDirectory, "onnxruntime.dll"));
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "webrtc_aec_plugin.dll"), Path.Combine(ThirdPartyLibrariesDirectory, "webrtc_aec_plugin.dll"));

            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "espeak_ng_data/..."), Path.Combine(ModuleDirectory, "espeak_ng_data/..."), StagedFileType.NonUFS);
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "icu_data/..."), Path.Combine(ModuleDirectory, "icu_data/..."), StagedFileType.NonUFS);

            PublicDefinitions.Add("INWORLD_WITH_CUDA=1");
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "CUDA", "inworld.dll"), Path.Combine(ThirdPartyLibrariesDirectory, "CUDA", "inworld.dll"));
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "CUDA", "onnxruntime.dll"), Path.Combine(ThirdPartyLibrariesDirectory, "CUDA", "onnxruntime.dll"));
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "CUDA", "webrtc_aec_plugin.dll"), Path.Combine(ThirdPartyLibrariesDirectory, "CUDA", "webrtc_aec_plugin.dll"));

            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "CUDA", "espeak_ng_data/..."), Path.Combine(ModuleDirectory, "espeak_ng_data/..."), StagedFileType.NonUFS);
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "CUDA", "icu_data/..."), Path.Combine(ModuleDirectory, "icu_data/..."), StagedFileType.NonUFS);
        }
        else if(Target.Platform == UnrealTargetPlatform.Linux)
        {
            PublicAdditionalLibraries.Add(Path.Combine(ThirdPartyLibrariesDirectory, "libinworld.so"));
            PublicDelayLoadDLLs.Add("libinworld.so");

            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "libinworld.so"), Path.Combine(ThirdPartyLibrariesDirectory, "libinworld.so"));
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "libonnxruntime.so.1"), Path.Combine(ThirdPartyLibrariesDirectory, "libonnxruntime.so.1"));
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "libonnxruntime_providers_shared.so"), Path.Combine(ThirdPartyLibrariesDirectory, "libonnxruntime_providers_shared.so"));
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "libgomp.so.1"), Path.Combine(ThirdPartyLibrariesDirectory, "libgomp.so.1"));
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "libwebrtc_aec_plugin.so"), Path.Combine(ThirdPartyLibrariesDirectory, "libwebrtc_aec_plugin.so"));

            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "espeak_ng_data/..."), Path.Combine(ModuleDirectory, "espeak_ng_data/..."), StagedFileType.NonUFS);
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "icu_data/..."), Path.Combine(ModuleDirectory, "icu_data/..."), StagedFileType.NonUFS);
        }
        else if(Target.Platform == UnrealTargetPlatform.Mac)
        {
            PublicAdditionalLibraries.Add(Path.Combine(ThirdPartyLibrariesDirectory, "libinworld.dylib"));
            PublicDelayLoadDLLs.Add(Path.Combine(ThirdPartyLibrariesDirectory, "libinworld.dylib"));

            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "libinworld.dylib"), Path.Combine(ThirdPartyLibrariesDirectory, "libinworld.dylib"));
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "libonnxruntime.dylib"), Path.Combine(ThirdPartyLibrariesDirectory, "libonnxruntime.dylib"));
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "libwebrtc_aec_plugin.dylib"), Path.Combine(ThirdPartyLibrariesDirectory, "libwebrtc_aec_plugin.dylib"));

            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "espeak_ng_data/..."), Path.Combine(ModuleDirectory, "espeak_ng_data/..."), StagedFileType.NonUFS);
            RuntimeDependencies.Add(Path.Combine(PluginBinariesDirectory, "icu_data/..."), Path.Combine(ModuleDirectory, "icu_data/..."), StagedFileType.NonUFS);
        }
    }

    internal bool TargetPlatformSupported
    {
        get
        {
            return Target.Platform == UnrealTargetPlatform.Win64
                || Target.Platform == UnrealTargetPlatform.Linux
                || Target.Platform == UnrealTargetPlatform.Mac;
        }
    }
}
