#![no_std]
#![no_main]

use esp_backtrace as _;
esp_bootloader_esp_idf::esp_app_desc!();
use esp_hal::{
    delay::Delay,
    gpio::{Level, Output, OutputConfig},
    main,
    spi::master::{Config, Spi},
    time::Rate,
};
use esp_println::println;

mod jd9853;

use jd9853::JD9853;
use mipidsi::{interface::SpiInterface, Builder};

use embedded_graphics::{
    mono_font::{ascii::FONT_10X20, MonoTextStyle},
    pixelcolor::Rgb565,
    prelude::*,
    primitives::{PrimitiveStyleBuilder, Rectangle},
    text::Text,
};

// TODO: verify pin assignments against your board schematic
//
// Typical wiring for a 1.47" JD9853 breakout on ESP32-C6:
//
//   Display pin  │ ESP32-C6 GPIO
//   ─────────────┼───────────────
//   SCL / SCK    │ GPIO6
//   SDA / MOSI   │ GPIO7
//   CS           │ GPIO10
//   DC           │ GPIO4
//   RST          │ GPIO5
//   BLK / BL     │ GPIO22 (set high to enable backlight)
//
const LCD_W: u16 = 172;
const LCD_H: u16 = 320;

#[main]
fn main() -> ! {
    let peripherals = esp_hal::init(esp_hal::Config::default());

    // 72 KB heap for mipidsi internal buffers, alloc, etc.
    esp_alloc::heap_allocator!(size: 72 * 1024);

    println!("ESP32-C6 display demo starting…");

    // --- SPI bus -----------------------------------------------------------
    let spi = Spi::new(
        peripherals.SPI2,
        Config::default()
            .with_frequency(Rate::from_mhz(40))
            .with_mode(esp_hal::spi::Mode::_0),
    )
    .unwrap()
    .with_sck(peripherals.GPIO1)
    .with_mosi(peripherals.GPIO2);

    // Manual chip-select via GPIO
    let cs = Output::new(peripherals.GPIO14, Level::High, OutputConfig::default());

    // Wrap bus + CS into an embedded-hal SpiDevice
    let spi_device = embedded_hal_bus::spi::ExclusiveDevice::new(spi, cs, Delay::new()).unwrap();

    // --- Display -----------------------------------------------------------
    let dc  = Output::new(peripherals.GPIO15, Level::Low, OutputConfig::default());
    let rst = Output::new(peripherals.GPIO22, Level::High, OutputConfig::default());

    // Backlight — drive high to enable
    let _bl = Output::new(peripherals.GPIO23, Level::High, OutputConfig::default());

    // mipidsi 0.10 requires a small scratch buffer owned by the interface
    let mut buf = [0u8; 512];
    let di = SpiInterface::new(spi_device, dc, &mut buf);

    // JD9853 has a 240-wide internal framebuffer; the 172-pixel panel starts at column 34.
    let mut display = Builder::new(JD9853, di)
        .reset_pin(rst)
        .display_size(LCD_W, LCD_H)
        .display_offset(34, 0)
        .init(&mut Delay::new())
        .expect("display init failed");

    // --- Drawing -----------------------------------------------------------
    display.clear(Rgb565::BLACK).unwrap();

    // Blue rectangle as background banner
    let bg_style = PrimitiveStyleBuilder::new()
        .fill_color(Rgb565::new(0, 0, 20))
        .build();
    Rectangle::new(Point::new(0, 0), Size::new(LCD_W as u32, 40))
        .into_styled(bg_style)
        .draw(&mut display)
        .unwrap();

    // White text
    let text_style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
    Text::new("ESP32-C6", Point::new(10, 28), text_style)
        .draw(&mut display)
        .unwrap();

    println!("Display ready.");

    loop {}
}
