// Some notes: 
// To generate the intermediate to see how many lines are being compiled, in x64 Native Tools Command Prompt for VS2022 or whatever
// cl /P /EP exe_main.cpp
// tokei exe_main.i
VERSION :: "0.1a";

#run,stallable build_cpp_project();

LIB_BASE_NAME :: "musa-lib";
EXE_BASE_NAME :: "musa";

LIB_SOURCE_FILENAMES :: string.["lib_main.cpp"];
EXE_SOURCE_FILENAMES :: string.["exe_main.cpp"];

INCLUDE_DIRS :: string.[
    "src",
    "lib", 
    "lib/api",
    "third_party"
];


build_cpp_project :: () {
    start := seconds_since_init();

    set_build_options_dc(.{do_output=false});
    options := get_build_options();
    args := options.compile_time_command_line;
    
    compile_debug := true;
    if array_find(args, "release") {  compile_debug = false;  }
    build_lib := array_find(args, "build_lib");
    build_exe := array_find(args, "build_exe");

    generate_meta_file(compile_debug);    
    if build_lib build_cpp_lib(compile_debug);
    if build_exe build_cpp_exe(compile_debug);
    
    print("\nFull build time: % seconds\n\n", FF(seconds_since_init() - start, 3));
}

build_cpp_exe :: (compile_debug: bool) {
    extra: [..]string;
    if os_target == {
        case .WINDOWS;  
          array_add(*extra, "-D_CRT_SECURE_NO_WARNINGS", "-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING", "-D_CRT_NONSTDC_NO_DEPRECATE");
          array_add(*extra, "-D_USE_MATH_DEFINES"); // , "-D_WIN32_WINNT=0x0A00", "/utf-8"
          
          array_add(*extra, "/MT"); // Static - The default

          for INCLUDE_DIRS  array_add(*extra, tprint("/I%", it));
        case; assert(false, "Other OSes not supported yet!");
    }
    
    exe_path := tprint("bin/%", EXE_BASE_NAME);
    make_directory_if_it_does_not_exist("bin");
    LINK_LIBS: []string;
    if (compile_debug) { LINK_LIBS = .["bin/Debug/dear-imgui.lib"]; } 
    else {               LINK_LIBS = .["bin/Release/dear-imgui.lib"]; }
    
    success := build_cpp_executable(exe_path, ..EXE_SOURCE_FILENAMES, debug=compile_debug, extra=extra, library_files=LINK_LIBS);
    print("\nbuild_cpp_executable, success: %\n", success);
}

build_cpp_lib :: (compile_debug: bool) -> bool {
    lib_path := tprint("bin/Debug/%", LIB_BASE_NAME);
    if !compile_debug {
        lib_path = tprint("bin/Release/%", LIB_BASE_NAME);
    }
    lib_directory := path_strip_filename(lib_path);
    make_directory_if_it_does_not_exist(lib_directory, recursive = true);
    print("Output lib_path: %\n\n", lib_path);
    
    extra: [..]string;
    if os_target == {
        case .WINDOWS;  
          array_add(*extra, "-D_CRT_SECURE_NO_WARNINGS", "-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING", "-D_CRT_NONSTDC_NO_DEPRECATE");
          array_add(*extra, "-D_USE_MATH_DEFINES"); // , "-D_WIN32_WINNT=0x0A00", "/utf-8"
          
          // array_add(*extra, "/MD"); // Dynamic 
          array_add(*extra, "/MT"); // Static - The default
          
          for INCLUDE_DIRS  array_add(*extra, tprint("/I%", it));
        case .LINUX;
          array_add(*extra, "-fPIC");
          array_add(*extra, tprint("-I/%/%", #filepath, "JIIM_Library"));
          for INCLUDE_DIRS  array_add(*extra, tprint("-I/%/%", #filepath, it));
        case; assert(false, "Other OSes not supported yet!");
    }
    
    success := build_cpp_static_lib(lib_path, ..LIB_SOURCE_FILENAMES, debug=compile_debug, extra=extra);
    print("\nbuild_cpp_static_lib, success: %\n", success);
    return success;
}

META_GENERATED_HEADER_FILE_PATH :: "lib/meta_generated.h";

cpu_target: CPU_Tag = .X64;
os_target: Operating_System_Tag = .WINDOWS;

generate_meta_file :: (debug: bool) {
    sb: String_Builder;
    append(*sb, "#pragma once\n\n");
    print_to_builder(*sb, "constexpr const char* MUSA_LIB_VERSION = \"%\";\n", VERSION);
    print_to_builder(*sb, "#define BUILD_DEBUG %\n", cast(s32)debug);
    
    print_to_builder(*sb, "#define OS_WINDOWS %\n", ifx os_target == .WINDOWS then 1 else 0);
    print_to_builder(*sb, "#define OS_LINUX %\n",   ifx os_target == .LINUX then 1 else 0);
    print_to_builder(*sb, "#define OS_MACOS %\n",   ifx os_target == .MACOS then 1 else 0);
    print_to_builder(*sb, "#define OS_ANDROID %\n", ifx os_target == .ANDROID then 1 else 0);
    print_to_builder(*sb, "#define OS_IOS %\n",     ifx os_target == .IOS then 1 else 0);
    
    print_to_builder(*sb, "#define ARCH_CPU_X64 %\n", ifx cpu_target == .X64 then 1 else 0);
    print_to_builder(*sb, "#define ARCH_CPU_ARM64 %\n", ifx cpu_target == .ARM64 then 1 else 0);
    
    os_is_unix := os_target == .MACOS || os_target == .LINUX || os_target == .IOS || os_target == .ANDROID;
    print_to_builder(*sb, "#define OS_IS_UNIX %\n", ifx os_is_unix then 1 else 0);
    
    print_to_builder(*sb, "#define COMPILER_MSVC %\n", ifx os_target == .WINDOWS then 1 else 0);
    print_to_builder(*sb, "#define COMPILER_CLANG %\n", ifx os_target != .WINDOWS then 1 else 0);
    
    print_to_builder(*sb, "#define ARRAY_ENABLE_BOUNDS_CHECKING %\n", cast(s32)debug);
    
    append(*sb, "#define COMPILER_GCC 0\n");
    
    meta_file_data := builder_to_string(*sb);
    write_entire_file(META_GENERATED_HEADER_FILE_PATH, meta_file_data);
    
    print("Generated meta header at % for % on %\n", META_GENERATED_HEADER_FILE_PATH, cpu_target, os_target);
}

#import "Basic";
#import "BuildCpp";
#import "Compiler";
#import "File";
#import "File_Utilities";
#import "String";
#import "System";
#import "Process";

#if OS == .WINDOWS {
    #import "Ico_File";
    #import "Windows_Resources";
    #import "Windows_Utf8";
}
// Note: Other operating systems are not supported for this application (yet).

FF :: (val: float64, width:=1) -> FormatFloat #expand {
    return formatFloat(val, trailing_width = width, zero_removal=.NO);
} @Utility