-- ==============================================
-- Easy2D for Nintendo Switch - Xmake Build Script
-- Purpose: Build Easy2D static library and Switch demo programs
-- Platform: Nintendo Switch (ARM64)
-- Graphics: Desktop OpenGL 3.3+ via Mesa EGL
-- Audio: SDL2_mixer
-- ==============================================

set_project("Easy2D")
set_version("3.1.0")
set_languages("c++17")
set_encodings("utf-8")
add_rules("mode.debug", "mode.release")

-- ==============================================
-- Nintendo Switch 工具链定义
-- ==============================================
toolchain("switch")
    set_kind("standalone")
    set_description("Nintendo Switch devkitA64 toolchain")

    -- 检查 DEVKITPRO 环境变量（Windows 上使用 C:/devkitPro）
    local devkitPro = "C:/devkitPro"
    local devkitA64 = path.join(devkitPro, "devkitA64")

    -- 设置工具链路径
    set_toolset("cc", path.join(devkitA64, "bin/aarch64-none-elf-gcc.exe"))
    set_toolset("cxx", path.join(devkitA64, "bin/aarch64-none-elf-g++.exe"))
    set_toolset("ld", path.join(devkitA64, "bin/aarch64-none-elf-g++.exe"))
    set_toolset("ar", path.join(devkitA64, "bin/aarch64-none-elf-gcc-ar.exe"))
    set_toolset("strip", path.join(devkitA64, "bin/aarch64-none-elf-strip.exe"))

    -- 架构标志
    local arch_flags = "-march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE"
    add_cxflags(arch_flags)
    -- 使用修复后的 switch_fix.specs 文件（使用 Windows 路径）
    add_ldflags("-specs=switch_fix.specs", "-g", arch_flags)

    -- 定义 Switch 平台宏
    add_defines("__SWITCH__", "__NX__", "MA_SWITCH", "PFD_SWITCH")
    
    -- SimpleIni 配置：不使用 Windows API
    add_defines("SI_NO_CONVERSION")
    
    -- OpenGL 配置：使用标准 GLES3.2
    add_defines("GL_GLES_PROTOTYPES")

    -- libnx 路径 - 必须在工具链级别添加
    add_includedirs(path.join(devkitPro, "libnx/include"))
    add_linkdirs(path.join(devkitPro, "libnx/lib"))
    
    -- portlibs 路径（EGL + 桌面 OpenGL + SDL2）
    add_includedirs(path.join(devkitPro, "portlibs/switch/include"))
    add_includedirs(path.join(devkitPro, "portlibs/switch/include/SDL2"))
    add_linkdirs(path.join(devkitPro, "portlibs/switch/lib"))
    
    add_syslinks("nx", "m")

-- 核心路径定义
local SRC_DIR = "Easy2D/src"
local INC_DIR = "Easy2D/include"

-- ==============================================
-- 1. Easy2D 静态库 (Switch 专用)
-- ==============================================
target("easy2d")
    set_kind("static")
    set_plat("switch")
    set_arch("arm64")
    set_toolchains("switch")
    set_basename(is_mode("debug") and "libeasy2dd" or "libeasy2d")

    -- 引擎源文件
    add_files(path.join(SRC_DIR, "**.cpp"))

    -- Squirrel 3.2 源文件
    add_files("squirrel/squirrel/*.cpp")
    add_files("squirrel/sqstdlib/*.cpp")

    -- 公开头文件目录
    add_includedirs(INC_DIR, {public = true})

    -- 第三方头文件目录
    add_includedirs("squirrel/include", {public = true})

    -- ==============================================
    -- Nintendo Switch 平台配置
    -- ==============================================

    -- devkitPro mesa 路径（EGL + 桌面 OpenGL）
    local devkitPro = "C:/devkitPro"
    add_includedirs(path.join(devkitPro, "portlibs/switch/include"), {public = true})
    add_linkdirs(path.join(devkitPro, "portlibs/switch/lib"))

    -- 使用系统 GLES3.2 头文件 (位于 devkitPro/portlibs/switch/include)

    -- 链接 EGL、OpenGL ES 3.0（mesa）和 SDL2 音频
    -- 注意：链接顺序很重要！SDL2 必须在 SDL2_mixer 之后
    add_syslinks("GLESv2", "EGL", "glapi", "drm_nouveau", 
                 "SDL2_mixer", "SDL2",
                 "opusfile", "opus", "vorbisidec", "ogg",
                 "modplug", "mpg123", "FLAC",
                 {public = true})

    -- 注意：pfd (portable-file-dialogs) 暂时禁用，需要进一步修复
    -- add_files(path.join(INC_DIR, "pfd/pfd_switch.cpp"))

    -- 添加 Switch 兼容性头文件路径
    add_includedirs(path.join(INC_DIR, "easy2d/platform"), {public = true})

    -- Switch 特定编译标志
    -- 注意：Squirrel 脚本绑定使用 dynamic_cast，需要 RTTI 支持
    -- add_cxflags("-fno-rtti", {force = true})
    add_cxflags("-Wno-unused-variable", "-Wno-unused-function", {force = true})
    
    -- Squirrel 第三方库警告抑制
    add_cxflags("-Wno-deprecated-copy", "-Wno-strict-aliasing", "-Wno-implicit-fallthrough", "-Wno-class-memaccess", {force = true})

    -- 使用 switch 工具链
    set_toolchains("switch")

    -- ==============================================
    -- 头文件安装配置
    -- ==============================================
    add_headerfiles(path.join(INC_DIR, "easy2d/**.h"), {prefixdir = "easy2d"})
    -- 使用 devkitPro 的 switch-glm 替代项目自带的 GLM
    -- add_headerfiles(path.join(INC_DIR, "glm/**.hpp"), {prefixdir = "glm"})
    add_headerfiles(path.join(INC_DIR, "stb/**.h"), {prefixdir = "stb"})
    add_headerfiles(path.join(INC_DIR, "simpleini/**.h"), {prefixdir = "simpleini"})

    -- 编译器配置
    add_cxxflags("-Wall", "-Wextra", {force = true})
    add_cxxflags("-Wno-unused-parameter", {force = true})
    if is_mode("debug") then
        add_defines("E2D_DEBUG", "_DEBUG", {public = true})
        add_cxxflags("-O0", "-g", {force = true})
    else
        add_defines("NDEBUG", {public = true})
        add_cxxflags("-O2", {force = true})
    end
target_end()

-- ==============================================
-- 2. Nintendo Switch 音频演示
-- ==============================================
target("switch_audio_demo")
    set_kind("binary")
    set_plat("switch")
    set_arch("arm64")
    set_toolchains("switch")
    
    add_files("Easy2D/examples/push_box/src/**.cpp")
    add_deps("easy2d")
    set_targetdir("$(builddir)/switch")
    
    -- 链接 EGL、OpenGL ES 3.0 和 SDL2 音频库
    -- 注意：链接顺序很重要！SDL2 必须在 SDL2_mixer 之后
    add_syslinks("GLESv2", "EGL", "glapi", "drm_nouveau", 
                 "SDL2_mixer", "SDL2",
                 "opusfile", "opus", "vorbisidec", "ogg",
                 "modplug", "mpg123", "FLAC")

    local appTitle = "Easy2D Switch Audio Demo"
    local appAuthor = "Easy2D Switch Audio Demo"
    local appVersion = "1.0.0"
    
    after_build(function (target)
        -- 强制使用 Windows 路径
        local devkitPro = "C:/devkitPro"
        local elf_file = target:targetfile()
        local output_dir = path.directory(elf_file)
        local nacp_file = path.join(output_dir, "switch_audio_demo.nacp")
        local nro_file = path.join(output_dir, "switch_audio_demo.nro")
        local romfs_dir = "Easy2D/examples/push_box/src/romfs"
        local nacptool = path.join(devkitPro, "tools/bin/nacptool.exe")
        local elf2nro = path.join(devkitPro, "tools/bin/elf2nro.exe")

        if not os.isfile(nacptool) then
            print("Warning: nacptool not found at " .. nacptool)
            return
        end
        if not os.isfile(elf2nro) then
            print("Warning: elf2nro not found at " .. elf2nro)
            return
        end

        -- 生成 .nacp 文件
        os.vrunv(nacptool, {"--create", appTitle, appAuthor, appVersion, nacp_file})
        print("Built " .. path.filename(nacp_file))

        -- 生成 .nro 文件（包含 RomFS）
        local romfs_absolute = path.absolute(romfs_dir)
        if os.isdir(romfs_absolute) then
            print("Packing RomFS from: " .. romfs_absolute)
            os.vrunv(elf2nro, {elf_file, nro_file, "--nacp=" .. nacp_file, "--romfsdir=" .. romfs_absolute})
            print("Built " .. path.filename(nro_file) .. " (with RomFS)")
        else
            os.vrunv(elf2nro, {elf_file, nro_file, "--nacp=" .. nacp_file})
            print("Built " .. path.filename(nro_file))
        end
    end)
target_end()

-- ============================================
-- Switch 简单测试程序
-- ============================================
target("switch_simple_test")
    set_kind("binary")
    set_targetdir("build/switch")
    
    -- 应用信息
    local appTitle = "Easy2D Simple Test"
    local appAuthor = "Easy2D Team"
    local appVersion = "1.0.0"
    
    -- 添加源文件
    add_files("Easy2D/examples/switch_simple_test/main.cpp")
    
    -- 添加头文件路径
    add_includedirs("Easy2D/include")
    
    -- 链接 easy2d 库
    add_deps("easy2d")
    

    -- 构建后生成 .nro 文件（包含 RomFS）
    after_build(function (target)
        local devkitPro = "C:/devkitPro"
        local elf_file = target:targetfile()
        local output_dir = path.directory(elf_file)
        local nacp_file = path.join(output_dir, "switch_simple_test.nacp")
        local nro_file = path.join(output_dir, "switch_simple_test.nro")
        local romfs_dir = "Easy2D/examples/switch_simple_test/romfs"
        local nacptool = path.join(devkitPro, "tools/bin/nacptool.exe")
        local elf2nro = path.join(devkitPro, "tools/bin/elf2nro.exe")
        
        if not os.isfile(nacptool) then
            print("Warning: nacptool not found at " .. nacptool)
            return
        end
        if not os.isfile(elf2nro) then
            print("Warning: elf2nro not found at " .. elf2nro)
            return
        end
        
        -- 生成 .nacp 文件
        os.vrunv(nacptool, {"--create", appTitle, appAuthor, appVersion, nacp_file})
        print("Built " .. path.filename(nacp_file))
        
        -- 生成 .nro 文件（包含 RomFS）
        local romfs_absolute = path.absolute(romfs_dir)
        if os.isdir(romfs_absolute) then
            print("Packing RomFS from: " .. romfs_absolute)
            os.vrunv(elf2nro, {elf_file, nro_file, "--nacp=" .. nacp_file, "--romfsdir=" .. romfs_absolute})
            print("Built " .. path.filename(nro_file) .. " (with RomFS)")
        else
            os.vrunv(elf2nro, {elf_file, nro_file, "--nacp=" .. nacp_file})
            print("Built " .. path.filename(nro_file))
        end
    end)
target_end()

