from __future__ import annotations

from .. import get_hw_model_as_number
from ..stm32u5_common import stm32u5_common_files


def configure(
    env: dict,
    features_wanted: list[str],
    defines: list[str | tuple[str, str]],
    sources: list[str],
    paths: list[str],
) -> list[str]:
    features_available: list[str] = []
    board = "T3W1/boards/trezor_t3w1_revA.h"
    hw_model = get_hw_model_as_number("T3W1")
    hw_revision = 0

    mcu = "STM32U5G9xx"
    linker_script = """embed/sys/linker/stm32u5g/{target}.ld"""
    memory_layout = "memory.ld"

    features_available += stm32u5_common_files(
        env, features_wanted, defines, sources, paths
    )

    ENV = env.get("ENV")
    assert ENV

    ENV["CPU_ASFLAGS"] = "-mthumb -mcpu=cortex-m33 -mfloat-abi=hard -mfpu=fpv5-sp-d16 "
    ENV["CPU_CCFLAGS"] = (
        "-mthumb -mcpu=cortex-m33 -mfloat-abi=hard -mfpu=fpv5-sp-d16 -mtune=cortex-m33 "
    )
    ENV["RUST_TARGET"] = "thumbv8m.main-none-eabihf"

    if "secure_domain" in features_wanted:
        ENV["CPU_CCFLAGS"] += "-mcmse "

    if "secmon_layout" in features_wanted:
        defines += [("USE_SECMON_LAYOUT", "1")]
        memory_layout = "memory_secmon.ld"
        features_available.append("secmon_layout")

    defines += [
        mcu,
        ("TREZOR_BOARD", f'"{board}"'),
        ("HW_MODEL", str(hw_model)),
        ("HW_REVISION", str(hw_revision)),
        ("HSE_VALUE", "32000000"),
        ("LSI_VALUE", "250"),
        ("USE_HSE", "1"),
        ("USE_LSE", "1"),
        ("USE_LSI", "1"),
        ("FIXED_HW_DEINIT", "1"),
        ("LOCKABLE_BOOTLOADER", "1"),
        ("LAZY_DISPLAY_INIT", "1"),
        ("USE_SECMON_VERIFICATION", "1"),
        ("USE_BOOTARGS_RSOD", "1"),
        ("TERMINAL_FONT_SCALE", "2"),
        ("TERMINAL_X_PADDING", "4"),
        ("TERMINAL_Y_PADDING", "12"),
    ]

    if "boot_ucb" in features_wanted:
        sources += ["embed/sec/image/boot_header.c"]
        sources += ["embed/sec/image/boot_ucb.c"]
        defines += [("USE_BOOT_UCB", "1")]
        features_available.append("boot_ucb")

    if "display" in features_wanted:
        sources += [
            "embed/io/display/ltdc_dsi/display_driver.c",
            "embed/io/display/ltdc_dsi/panels/lx250a2401a/lx250a2401a.c",
            "embed/io/display/ltdc_dsi/display_fb.c",
            "embed/io/display/ltdc_dsi/display_fb_rgb888.c",
            "embed/io/display/ltdc_dsi/display_gfxmmu.c",
            "embed/io/display/fb_queue/fb_queue.c",
        ]
        paths += ["embed/io/display/inc"]
        defines += [("USE_DISPLAY", "1")]

        features_available.append("backlight")
        defines += [("USE_BACKLIGHT", "1")]
        sources += ["embed/io/backlight/stm32u5/tps61062.c"]
        paths += ["embed/io/backlight/inc"]

    if "input" in features_wanted:
        sources += ["embed/io/touch/ft3168/ft3168.c"]
        sources += ["embed/io/touch/ft3168/panels/lx250a2410a.c"]
        sources += ["embed/io/touch/touch_poll.c"]
        paths += ["embed/io/touch/inc"]
        features_available.append("touch")
        sources += ["embed/io/button/stm32/button.c"]
        sources += ["embed/io/button/button_poll.c"]
        paths += ["embed/io/button/inc"]
        features_available.append("button")
        defines += [
            ("USE_TOUCH", "1"),
            ("USE_BUTTON", "1"),
        ]

    sources += ["embed/sys/i2c_bus/stm32u5/i2c_bus.c"]
    paths += ["embed/sys/i2c_bus/inc"]
    defines += [("USE_I2C", "1")]

    sources += [
        "embed/sec/backup_ram/backup_ram_crc.c",
        "embed/sec/backup_ram/stm32u5/backup_ram.c",
    ]
    paths += ["embed/sec/backup_ram/inc"]
    defines += [("USE_BACKUP_RAM", "1")]

    if "rtc" in features_wanted:
        sources += ["embed/sys/time/stm32u5/rtc.c"]
        defines += [("USE_RTC", "1")]

    if "haptic" in features_wanted:
        sources += [
            "embed/io/haptic/drv262x/drv262x.c",
        ]
        paths += ["embed/io/haptic/inc"]
        features_available.append("haptic")
        defines += ["USE_HAPTIC=1"]

    if "ble" in features_wanted:
        sources += ["embed/io/ble/stm32/ble.c"]
        paths += ["embed/io/ble/inc"]
        features_available.append("ble")
        defines += [("USE_BLE", "1")]
        sources += ["embed/io/nrf/stm32u5/nrf.c"]
        sources += ["embed/io/nrf/stm32u5/nrf_spi.c"]
        sources += ["embed/io/nrf/stm32u5/nrf_update.c"]
        sources += ["embed/io/nrf/crc8.c"]
        paths += ["embed/io/nrf/inc"]
        features_available.append("nrf")
        defines += [("USE_NRF", "1")]
        sources += [
            "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_uart.c",
            "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_uart_ex.c",
        ]
    if "nrf_auth" in features_wanted or "ble" in features_wanted:
        defines += [("USE_NRF_AUTH", "1")]

    if "ble" in features_wanted and "smp" in features_wanted:
        sources += ["embed/io/nrf/stm32u5/nrf_uart.c"]
        sources += ["embed/io/nrf/stm32u5/nrf_test.c"]
        features_available.append("smp")
        defines += [("USE_SMP", "1")]

    if "nfc" in features_wanted:
        sources += ["embed/io/nfc/st25r3916b/nfc.c"]
        sources += ["embed/io/nfc/st25r3916b/ndef.c"]
        sources += ["embed/io/nfc/st25r3916b/card_emulation.c"]
        sources += ["embed/io/nfc/rfal/source/st25r3916/rfal_rfst25r3916.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_analogConfig.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_nfc.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_nfca.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_nfcb.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_nfcf.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_nfcv.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_isoDep.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_nfcDep.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_st25tb.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_t1t.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_t2t.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_iso15693_2.c"]
        sources += ["embed/io/nfc/rfal/source/rfal_crc.c"]
        sources += ["embed/io/nfc/rfal/source/st25r3916/st25r3916.c"]
        sources += ["embed/io/nfc/rfal/source/st25r3916/st25r3916_com.c"]
        sources += ["embed/io/nfc/rfal/source/st25r3916/st25r3916_led.c"]
        sources += ["embed/io/nfc/rfal/source/st25r3916/st25r3916_irq.c"]
        paths += ["embed/io/nfc/inc/"]
        paths += ["embed/io/nfc/st25r3916b/"]
        paths += ["embed/io/nfc/rfal/source"]
        paths += ["embed/io/nfc/rfal/source/st25r3916"]
        paths += ["embed/io/nfc/rfal/include/"]
        defines += [("USE_NFC", "1")]

    if "optiga" in features_wanted:
        sources += ["embed/sec/optiga/stm32/optiga_hal.c"]
        sources += ["embed/sec/optiga/optiga.c"]
        sources += ["embed/sec/optiga/optiga_commands.c"]
        sources += ["embed/sec/optiga/optiga_config.c"]
        sources += ["embed/sec/optiga/optiga_transport.c"]
        sources += ["vendor/trezor-crypto/hash_to_curve.c"]
        paths += ["embed/sec/optiga/inc"]
        features_available.append("optiga")
        defines += [("USE_OPTIGA", "1")]

    if "tropic" in features_wanted:
        sources += ["embed/sec/tropic/tropic.c"]
        sources += ["embed/sec/tropic/stm32/tropic01.c"]
        sources += ["vendor/libtropic/cal/trezor_crypto/lt_trezor_crypto_aesgcm.c"]
        sources += ["vendor/libtropic/cal/trezor_crypto/lt_trezor_crypto_common.c"]
        sources += ["vendor/libtropic/cal/trezor_crypto/lt_trezor_crypto_hmac_sha256.c"]
        sources += ["vendor/libtropic/cal/trezor_crypto/lt_trezor_crypto_sha256.c"]
        sources += ["vendor/libtropic/cal/trezor_crypto/lt_trezor_crypto_x25519.c"]
        sources += ["vendor/libtropic/src/libtropic.c"]
        sources += ["vendor/libtropic/src/libtropic_l2.c"]
        sources += ["vendor/libtropic/src/libtropic_l3.c"]
        sources += ["vendor/libtropic/src/lt_asn1_der.c"]
        sources += ["vendor/libtropic/src/lt_crc16.c"]
        sources += ["vendor/libtropic/src/lt_hkdf.c"]
        sources += ["vendor/libtropic/src/lt_l1.c"]
        sources += ["vendor/libtropic/src/lt_l2_frame_check.c"]
        sources += ["vendor/libtropic/src/lt_l3_process.c"]
        sources += ["vendor/libtropic/src/lt_port_wrap.c"]
        sources += ["vendor/libtropic/src/lt_tr01_attrs.c"]
        paths += ["embed/sec/tropic/inc"]
        paths += ["vendor/libtropic/include"]
        paths += ["vendor/libtropic/src"]
        features_available.append("tropic")
        defines += [("USE_TROPIC", "1")]
        defines += [("LT_USE_TREZOR_CRYPTO", "1")]
        defines += [("LT_HELPERS", "1")]

        paths += ["vendor/libtropic/TROPIC01_fw_update_files/boot_v_1_0_1/fw_v_1_0_0"]
        defines += [("ABAB", "1")]

    if "sbu" in features_wanted:
        sources += ["embed/io/sbu/stm32/sbu.c"]
        paths += ["embed/io/sbu/inc"]
        features_available.append("sbu")
        defines += [("USE_SBU", "1")]

    if "rgb_led" in features_wanted:
        sources += ["embed/io/rgb_led/stm32/rgb_led.c"]
        paths += ["embed/io/rgb_led/inc"]
        features_available.append("rgb_led")
        defines += [("USE_RGB_LED", "1")]

    defines += [
        "FRAMEBUFFER",
        "DISPLAY_RGBA8888",
        ("UI_COLOR_32BIT", "1"),
        ("USE_RGB_COLORS", "1"),
        ("DISPLAY_RESX", "380"),
        ("DISPLAY_RESY", "520"),
    ]
    features_available.append("ui_color_32bit")
    features_available.append("framebuffer")
    features_available.append("display_rgba8888")

    defines += [
        "USE_DMA2D",
    ]
    features_available.append("dma2d")
    sources += ["embed/io/gfx/bitblt/stm32/dma2d_bitblt.c"]

    defines += ["USE_HW_JPEG_DECODER"]
    features_available.append("hw_jpeg_decoder")
    sources += [
        "embed/io/gfx/jpegdec/stm32u5/jpegdec.c",
    ]

    defines += [
        ("USE_HASH_PROCESSOR", "1"),
        ("USE_STORAGE_HWKEY", "1"),
        ("USE_TAMPER", "1"),
        ("USE_FLASH_BURST", "1"),
        ("USE_OEM_KEYS_CHECK", "1"),
    ]

    if ("pmic" in features_wanted) or ("power_manager" in features_wanted):
        sources += ["embed/io/power_manager/npm1300/npm1300.c"]
        paths += ["embed/io/power_manager/inc"]
        defines += ["USE_PMIC"]
        features_available.append("pmic")

    if "suspend" in features_wanted:
        sources += [
            "embed/io/suspend/stm32u5/suspend.c",
            "embed/io/suspend/stm32u5/suspend_io.c",
            "embed/sec/suspend/stm32u5/suspend_io.c",
        ]
        paths += [
            "embed/io/suspend/inc",
            "embed/sec/suspend/inc",
        ]
        defines += [("USE_SUSPEND", "1")]

    if "power_manager" in features_wanted:
        sources += [
            "embed/io/power_manager/stm32u5/power_manager.c",
            "embed/io/power_manager/stm32u5/power_monitoring.c",
            "embed/io/power_manager/stm32u5/power_states.c",
            "embed/io/power_manager/battery/battery.c",
            "embed/io/power_manager/battery/fuel_gauge.c",
            "embed/io/power_manager/battery/battery_model.c",
            "embed/io/power_manager/stwlc38/stwlc38.c",
            "embed/io/power_manager/stwlc38/stwlc38_patching.c",
            "embed/io/power_manager/power_manager_poll.c",
        ]
        paths += ["embed/io/power_manager/inc"]
        defines += [("USE_POWER_MANAGER", "1")]
        features_available.append("power_manager")

    if "iwdg" in features_wanted:
        sources += ["embed/sec/iwdg/stm32/iwdg.c"]
        sources += [
            "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_iwdg.c",
        ]
        paths += ["embed/sec/iwdg/inc"]
        defines += [("USE_IWDG", "1")]

    if "serial_number" in features_wanted:
        defines += [("USE_SERIAL_NUMBER", "1")]
        features_available.append("serial_number")

    ENV["LINKER_SCRIPT"] = linker_script
    ENV["MEMORY_LAYOUT"] = memory_layout

    return features_available
