#ifndef LGFX_USE_V1
#define LGFX_USE_V1
#endif

#include "app/hardware/obb_lgfx_station_s.h"

namespace obb::hardware {

namespace {

constexpr int kPinLcdCs = 15;
constexpr int kPinLcdDc = 2;
constexpr int kPinLcdRst = -1;
constexpr int kPinSpiMosi = 13;
constexpr int kPinSpiMiso = 12;
constexpr int kPinSpiClk = 14;
constexpr int kPinBacklight = 27;

class LGFXStationS : public lgfx::LGFX_Device {
public:
  LGFXStationS() {
    configure_bus();
    configure_panel();
    configure_backlight();
  }

private:
  void configure_bus() {
    auto bus_cfg = bus_.config();
    bus_cfg.spi_host = VSPI_HOST;
    bus_cfg.spi_mode = 0;
    bus_cfg.freq_write = 40000000;
    bus_cfg.freq_read = 16000000;
    bus_[cfg.pin](<http://cfg.pin>)_sclk = kPinSpiClk;
    bus_[cfg.pin](<http://cfg.pin>)_mosi = kPinSpiMosi;
    bus_[cfg.pin](<http://cfg.pin>)_miso = kPinSpiMiso;
    bus_[cfg.pin](<http://cfg.pin>)_dc = kPinLcdDc;
    bus_cfg.dma_channel = 1;
    bus_.config(bus_cfg);
    panel_.setBus(&bus_);
  }

  void configure_panel() {
    auto panel_cfg = panel_.config();
    panel_[cfg.pin](<http://cfg.pin>)_cs = kPinLcdCs;
    panel_[cfg.pin](<http://cfg.pin>)_rst = kPinLcdRst;
    panel_[cfg.pin](<http://cfg.pin>)_busy = -1;
    panel_cfg.memory_width = 320;
    panel_cfg.memory_height = 480;
    panel_cfg.panel_width = 320;
    panel_cfg.panel_height = 480;
    panel_cfg.offset_x = 0;
    panel_cfg.offset_y = 0;
    panel_cfg.offset_rotation = 0;
    panel_cfg.dlen_16bit = false;
    panel_cfg.bus_shared = false;
    panel_cfg.invert = false;
    panel_cfg.rgb_order = false;
    panel_cfg.readable = false;
    panel_.config(panel_cfg);
    setPanel(&panel_);
  }

  void configure_backlight() {
    auto light_cfg = light_.config();
    light_[cfg.pin](<http://cfg.pin>)_bl = kPinBacklight;
    light_cfg.freq = 44100;
    light_cfg.pwm_channel = 7;
    light_.config(light_cfg);
    panel_.setLight(&light_);
  }

  lgfx::Bus_SPI bus_;
  lgfx::Panel_ST7796 panel_;
  lgfx::Light_PWM light_;
};

LGFXStationS &DisplayInstance() {
  static LGFXStationS instance;
  return instance;
}

}  // namespace

lgfx::LGFX_Device &station_s_display() {
  return DisplayInstance();
}

}  // namespace obb::hardware