// Copyright 2026 sbqrre
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

///|
fn main {
  println("==================================================================")
  println("  MoonBit MCU HAL - Hardware Abstraction Layer & Simulation Suite")
  println("==================================================================")

  // 1. Device Capabilities
  let caps = @types.DeviceCapability::default()
  println(caps.summary())

  // 2. System Clock & Delay Setup
  let clk = @clock_delay.HalClock::default_clock()
  let delay = @clock_delay.HalDelay::new(clk)
  println(clk.to_string())
  delay.delay_ms(100)
  println(
    "Clock Ticks after 100ms delay: " + clk.get_ticks_us().to_string() + "us",
  )

  // 3. GPIO Configuration
  let pin_spec = @types.PinSpec::new(@types.PortId::PortA, 5, 0)
  let gpio_cfg = @gpio.GpioConfig::default_output(pin_spec)
  let pin = @gpio.GpioPin::new(gpio_cfg)
  let _ = pin.set_high()
  println("GPIO Pin Status: " + pin.to_string())

  // 4. UART Serial Port
  let uart_cfg = @uart.UartConfig::standard_115200()
  let uart = @uart.UartPort::new(uart_cfg)
  let _ = uart.write_string("MoonBit MCU HAL Initialized!\r\n")
  println(
    "UART Port Status: " +
    uart.to_string() +
    ", TX pending=" +
    uart.tx_pending().to_string(),
  )

  // 5. SPI Master Controller
  let spi_cfg = @spi.SpiConfig::default_config()
  let spi = @spi.SpiMaster::new(spi_cfg, None)
  let tx_block = @spi.SpiTransaction::transfer([(0x9F : Byte), (0x00 : Byte)])
  let spi_rx = spi.execute_transaction(tx_block).unwrap()
  println(
    "SPI Transaction Execution Success. RX Bytes count: " +
    spi_rx.length().to_string(),
  )

  // 6. I2C Master & Simulated EEPROM Target
  let i2c_cfg = @i2c.I2cConfig::default_config()
  let i2c = @i2c.I2cMaster::new(i2c_cfg)
  let eeprom_addr = @i2c.I2cAddress::Addr7Bit(0x50)
  let eeprom = @sim.At24c02Eeprom::attach(i2c, eeprom_addr)
  let _ = eeprom.write_byte(0x00, (0x42 : Byte))
  let eeprom_val = eeprom.read_byte(0x00).unwrap()
  println(
    "I2C AT24C02 EEPROM Read at 0x00: 0x" + eeprom_val.to_int().to_string(),
  )

  // 7. PWM Motor Timer
  let pwm_cfg = @pwm.PwmConfig::default_config()
  let pwm = @pwm.PwmTimer::new(pwm_cfg, 1000)
  let _ = pwm.set_duty_cycle(@pwm.PwmChannel::Channel1, 0.75)
  println(
    "PWM Motor Channel 1 Duty Cycle: " +
    (pwm.get_duty_cycle(@pwm.PwmChannel::Channel1) * 100.0).to_string() +
    "%, Pulse Ticks=" +
    pwm.get_pulse_ticks(@pwm.PwmChannel::Channel1).to_string(),
  )

  // 8. ADC Voltage Sampler
  let adc_cfg = @adc.AdcConfig::default_config()
  let adc = @adc.AdcController::new(adc_cfg)
  adc.set_simulated_channel_mv(0, 1650)
  let adc_mv = adc.read_mv(0).unwrap()
  println("ADC Channel 0 Sampled Voltage: " + adc_mv.to_string() + "mV")

  // 9. Hardware Timer & Real-Time Clock (RTC)
  let timer = @timer.HardwareTimer::new(clk, @timer.TimerMode::OneShot, 1, 1000)
  let _ = timer.start()
  let rtc = @rtc.RtcClock::default_rtc()
  rtc.tick_second()
  println("RTC Current Time: " + rtc.get_datetime().to_string())

  // 10. DMA Engine
  let dma_cfg = @dma.DmaConfig::default_mem2mem()
  let dma = @dma.DmaChannel::new(1, dma_cfg)
  let src_buf : Array[Byte] = [(0x01 : Byte), (0x02 : Byte), (0x03 : Byte)]
  let dst_buf : Array[Byte] = [(0x00 : Byte), (0x00 : Byte), (0x00 : Byte)]
  let _ = dma.transfer_buffer(src_buf, dst_buf, 3)
  println("DMA Transferred Bytes: " + dma.get_transferred_bytes().to_string())

  // 11. Concurrency Protection Mutex
  let mutex = @lock.PeripheralMutex::new("SPI1_Bus", "SPI Master Resource")
  let _ = mutex.acquire(1)
  println("Peripheral Lock Status: " + mutex.to_string())
  let _ = mutex.release(1)

  // 12. Virtual MCU System Simulation
  let v_mcu = @sim.VirtualMcuSystem::default_sim()
  v_mcu.registers().write_reg(0x04, 0xCAFEBABE)
  println(
    "Virtual MCU MMIO Register [0x04]: 0x" +
    v_mcu.registers().read_reg(0x04).to_string(),
  )

  // 13. Chip Adaptation Layers (STM32, RP2040, ESP32)
  let bank = @sim.VirtualRegisterBank::new(@types.RegAddr::new(0x40000000))
  let stm_gpio = @stm32.Stm32GpioPort::new(@types.PortId::PortA, bank)
  stm_gpio.write_bsrr(5, @types.PinState::High)

  let rp_sio = @rp2040.Rp2040Sio::new(bank)
  rp_sio.gpio_set_high(25)

  let esp_matrix = @esp32.Esp32GpioMatrix::new(bank)
  esp_matrix.set_high(2)
  println(
    "MCU Target Adaptation Layers (STM32, RP2040 Pico, ESP32) Successfully Executed!",
  )

  // 14. Device Tree Parser
  let dts_parser = @dts.DtsParser::new(
    "usart1: serial@40011000 { status = \"okay\"; };",
  )
  let dt = dts_parser.parse_simple_peripheral("usart1", 0x40011000, "okay")
  println(
    "Device Tree Descriptor Node Count: " +
    dt.root_node.children.length().to_string(),
  )

  // 15. Embedded RTOS Scheduler
  let sched = @rtos.RtosScheduler::new()
  let _ = sched.create_task(1, "SensorTask", 2)
  let _ = sched.create_task(2, "ControlLoop", 10)
  let scheduled_task = sched.schedule_tick().unwrap()
  println("RTOS Context Switch Active Task ID: " + scheduled_task.to_string())

  // 16. Board Support Package (BSP)
  let bsp_pico = @bsp.BoardSupportPackage::init_pico()
  let _ = bsp_pico.toggle_status_led()
  println(bsp_pico.to_string() + " Ready.")

  // 17. Run Extended Demonstration Scenarios
  run_environmental_monitor_demo()
  run_motor_control_demo()
  run_data_logger_demo()

  println("==================================================================")
  println("  MoonBit MCU HAL Integration Test Complete!")
  println("==================================================================")
}