#include "External/SDK/VisualStudio/VisualStudio.bff"
#include "External/SDK/Clang/Clang.bff"
#include "External/SDK/Windows/Windows.bff"

//------------------------------------------------------------------------------
// Settings
//------------------------------------------------------------------------------
Settings
{
    .CachePath = 'C:\FASTBuild_Cache\' // Use a local SSD or network path
    #if __WINDOWS__
        #import TMP
        .Environment    = { "PATH=$VS_PATH$;$WINDOWS_SDK_2019_PATH$",
                            "TMP=$TMP$",
                            "SystemRoot=C:\Windows" }
    #endif
}

//------------------------------------------------------------------------------
// Global Output Paths
//------------------------------------------------------------------------------
.BinPath        = 'bin'
.OutputBase     = 'Intermediate'
.CommonWinLibs = ' kernel32.lib user32.lib gdi32.lib dxguid.lib Ws2_32.lib dxgi.lib imm32.lib dwmapi.lib d3dcompiler.lib shell32.lib'


.ProjectConfigs = {}

//------------------------------------------------------------------------------
// Config Defines
//------------------------------------------------------------------------------
.Debug_Config =
[
    .CompilerOptions                = ' -DDEBUG -DPROFILING_ENABLED -DJULIET_ENABLE_IMGUI'
    .CompilerOptionsC               = .CompilerOptions
    .BuildConfigName                = 'Debug'
]
.Profile_Config =
[
    .CompilerOptions                = ' -DRELEASE -DPROFILING_ENABLED'
    .CompilerOptionsC               = .CompilerOptions
    .BuildConfigName                = 'Profile'
]
.Release_Config =
[
    .CompilerOptions                = ' -DRELEASE'
    .CompilerOptionsC               = .CompilerOptions
    .CompilerOptionsDeoptimized     = .CompilerOptions
    .BuildConfigName                = 'Release'
]

//------------------------------------------------------------------------------
// Optimizations (MSVC)
//------------------------------------------------------------------------------
#if __WINDOWS__
    .Debug_Optimizations_MSVC =
    [
        .CompilerOptions                = ' /MDd /Od /RTC1 /GS /Oy-'
        .CompilerOptionsC               = .CompilerOptions
    ]
    .Profile_Optimizations_MSVC =
    [
        .CompilerOptions                = ' /MD /Ox /Oy /Oi /GS- /GF /Gy /Gw /Zo'
        .CompilerOptionsC               = .CompilerOptions
        .LinkerOptions                  = ' /OPT:REF,ICF'
    ]
    .Release_Optimizations_MSVC =
    [
        Using( .Profile_Optimizations_MSVC )
        .CompilerOptionsDeoptimized     = .CompilerOptions
                                        - ' /Ox'
                                        + ' /Od'
    ]
#endif

//------------------------------------------------------------------------------
// Optimizations (Clang/GCC)
//------------------------------------------------------------------------------
.Debug_Optimizations =
[
    #if __WINDOWS__ // Using clang-cl.exe on Windows
        .CompilerOptions                = ' /MDd /Od'
    #else
        .CompilerOptions                = ' -O0'
    #endif
    .CompilerOptionsC               = .CompilerOptions
]
.Profile_Optimizations =
[
    .CompilerOptions                = ' -O2'

    #if __WINDOWS__ // Using clang-cl.exe on Windows
        .CompilerOptions            + ' /MD'
    #endif

    .CompilerOptionsC               = .CompilerOptions
]
.Release_Optimizations =
[
    Using( .Profile_Optimizations )
    .CompilerOptionsDeoptimized     = .CompilerOptions
                                    - ' -O2'
                                    + ' -O0'
]

// X64
//------------------------------------------------------------------------------
#if __WINDOWS__
    .X64BaseConfig              = .ToolChain_VS_Windows_X64
                                + .Windows10_SDK_X64
    .X64DebugConfig             = .X64BaseConfig
                                + .Debug_Config
                                + .Debug_Optimizations_MSVC
    .X64ReleaseConfig           = .X64BaseConfig
                                + .Release_Config
                                + .Release_Optimizations_MSVC
    .X64ProfileConfig           = .X64BaseConfig
                                + .Profile_Config
                                + .Profile_Optimizations_MSVC
#endif

// X64 Clang
//------------------------------------------------------------------------------
#if __WINDOWS__
    .X64ClangBaseConfig         = .ToolChain_Clang_Windows
                                + .Windows10_SDK_X64_ClangCl
    .X64ClangDebugConfig        = .X64ClangBaseConfig
                                + .Debug_Config
                                + .Debug_Optimizations
    .X64ClangReleaseConfig      = .X64ClangBaseConfig
                                + .Release_Config
                                + .Release_Optimizations
    .X64ClangProfileConfig      = .X64ClangBaseConfig
                                + .Profile_Config
                                + .Profile_Optimizations
#endif


//------------------------------------------------------------------------------
// VisualStudio Project Generation
//------------------------------------------------------------------------------
#if __WINDOWS__
    .ProjectCommon =
    [
        .ProjectBuildCommand            = 'cd ^$(SolutionDir) & misc\fbuild -ide -dist -monitor -cache ^$(ProjectName)-^$(Configuration)'
        .ProjectRebuildCommand          = 'cd ^$(SolutionDir) & misc\fbuild -ide -dist -monitor -cache -clean ^$(ProjectName)-^$(Configuration)'
        .OutputDirectory                = '^$(SolutionDir)\bin'
        .IntermediateDirectory          = '^$(SolutionDir)\Intermediate'
        .BuildLogFile                   = '^$(SolutionDir)\Intermediate\^$(ProjectName)-^$(Configuration).log'
        .Platform                       = 'x64'
        .PlatformToolset                = '$VS_PlatformToolset$'
        .LocalDebuggerCommand           = '^$(SolutionDir)\bin\^$(Configuration)\^$(ProjectName).exe'
        .LocalDebuggerWorkingDirectory  = '^$(SolutionDir)\bin\^$(Configuration)\'
    ]

    .Project_x64_Debug        = [ Using( .ProjectCommon ) .SolutionPlatform = 'x64'         .SolutionConfig = 'Debug'   .Config = '$SolutionPlatform$-$SolutionConfig$' ]
    .Project_x64_Profile      = [ Using( .ProjectCommon ) .SolutionPlatform = 'x64'         .SolutionConfig = 'Profile' .Config = '$SolutionPlatform$-$SolutionConfig$' ]
    .Project_x64_Release      = [ Using( .ProjectCommon ) .SolutionPlatform = 'x64'         .SolutionConfig = 'Release' .Config = '$SolutionPlatform$-$SolutionConfig$' ]
    .Project_x64Clang_Debug   = [ Using( .ProjectCommon ) .SolutionPlatform = 'x64Clang'    .SolutionConfig = 'Debug'   .Config = '$SolutionPlatform$-$SolutionConfig$' ]
    .Project_x64Clang_Profile = [ Using( .ProjectCommon ) .SolutionPlatform = 'x64Clang'    .SolutionConfig = 'Profile' .Config = '$SolutionPlatform$-$SolutionConfig$' ]
    .Project_x64Clang_Release = [ Using( .ProjectCommon ) .SolutionPlatform = 'x64Clang'    .SolutionConfig = 'Release' .Config = '$SolutionPlatform$-$SolutionConfig$' ]
#endif

// Configurations
//------------------------------------------------------------------------------
#if __WINDOWS__
    .BuildConfigs               = { .X64DebugConfig, .X64ProfileConfig, .X64ReleaseConfig
                                    .X64ClangDebugConfig, .X64ClangProfileConfig, .X64ClangReleaseConfig }
#endif

.Targets_x64_Debug = {}
.Targets_x64_Profile = {}
.Targets_x64_Release = {}
.Targets_x64Clang_Debug = {}
.Targets_x64Clang_Profile = {}
.Targets_x64Clang_Release = {}

// Include all projects to build
#include "External/Imgui.bff"
#include "Juliet/Juliet.bff"
#include "Game/Game.bff"
#include "JulietApp/JulietApp.Bff"
#include "JulietShaderCompiler/JulietShaderCompiler.Bff"


// Aliases : All-$Platform$-$Config$
//------------------------------------------------------------------------------
ForEach( .BuildConfig in .BuildConfigs )
{
    Using( .BuildConfig )
    Alias( 'All-$Platform$-$BuildConfigName$' ) { .Targets = .'Targets_$Platform$_$BuildConfigName$' }
}

// Exes
//------------------------------------------------------------------------------
Alias( 'Exes' )
{
    .Targets    = { 'JulietApp-Debug',   'JulietApp-Profile', 'JulietApp-Release' }
}

// Aliases : All-$Platform$
//------------------------------------------------------------------------------
.Platforms                     = { 'x64', 'x64Clang' }
.PlatformConfigs_x64           = { 'Debug', 'Profile', 'Release' }
.PlatformConfigs_x64Clang      = { 'Debug', 'Profile', 'Release' }

ForEach( .Platform in .Platforms )
{
    Alias( 'All-$Platform$' )
    {
        .Targets = {}
        ForEach( .Config in .'PlatformConfigs_$Platform$' )
        {
                ^Targets + { 'All-$Platform$-$Config$' }
        }
    }
}

// Aliases : All
//------------------------------------------------------------------------------
#if __WINDOWS__
    Alias( 'All' )
    {
        .Targets        = { 'All-x64Clang',
                            'All-x64',
                          }
    }
#endif

//------------------------------------------------------------------------------
// Intuitive Aliases (msvc / clang)
//------------------------------------------------------------------------------

// 1. Map 'msvc' and 'clang' to the full platform builds
Alias( 'msvc' )  { .Targets = 'All-x64' }
Alias( 'clang' ) { .Targets = 'All-x64Clang' }

// 2. Map specific compiler + config combinations
.Configs = { 'Debug', 'Profile', 'Release' }
ForEach( .Config in .Configs )
{
    // Allows: fbuild msvc-debug, fbuild msvc-release, etc.
    Alias( 'msvc-$Config$' )  { .Targets = 'All-x64-$Config$' }
    
    // Allows: fbuild clang-debug, fbuild clang-release, etc.
    Alias( 'clang-$Config$' ) { .Targets = 'All-x64Clang-$Config$' }
}

// 3. Map config-only aliases across both compilers
// Allows: fbuild debug, fbuild release
ForEach( .Config in .Configs )
{
    Alias( '$Config$' ) { .Targets = { 'msvc-$Config$', 'clang-$Config$' } }
}

// Generate solution
VSSolution( 'GenerateSolution' )
{
    .SolutionOutput   = 'Juliet.sln'
    .SolutionProjects = { 'Juliet', 'Game', 'JulietApp', 'ImGui' }

    .SolutionConfigs  = .ProjectConfigs
    .SolutionBuildProject = 'JulietApp'
}
Alias( 'gen' ) { .Targets = 'GenerateSolution' }
