#ifndef _THINKINK_270_GRAY4_W3_H
#define _THINKINK_270_GRAY4_W3_H

#include "Adafruit_EPD.h"

// clang-format off

static const uint8_t ti_270w3_gray4_init_code[] {
    IL91874_POWER_SETTING, 4, 0x03, 0x00, 0x2b, 0x2b,
    IL91874_BOOSTER_SOFT_START, 3, 0x07, 0x07, 0x17,
    0xF8, 2, 0x60, 0xA5, // boost
    0xF8, 2, 0x89, 0xA5, // boost
    0xF8, 2, 0x90, 0x00, // boost
    0xF8, 2, 0x93, 0x2A, // boost
    0xF8, 2, 0xA0, 0xA5, // boost
    0xF8, 2, 0xA1, 0x00, // boost
    0xF8, 2, 0x73, 0x41, // boost
    IL91874_PDRF, 1, 0x00,
    IL91874_POWER_ON, 0,
    0xFF, 200,
    IL91874_PANEL_SETTING, 1, 0xBF,
    IL91874_PLL, 1, 0x90,
    IL91874_VCM_DC_SETTING, 1, 0x12,
    IL91874_CDI, 1, 0x97,
    0xFE // EOM
};


static const uint8_t ti_270w3_gray4_lut_code[] = {
  // const unsigned char lut_vcom[]PROGMEM =
  IL91874_LUT1, 44,
  0x00, 0x00,
  0x00 , 0x0A, 0x00, 0x00, 0x00, 0x01,
  0x60, 0x14, 0x14, 0x00, 0x00, 0x01,
  0x00, 0x14, 0x00, 0x00, 0x00, 0x01,
  0x00, 0x13, 0x0A, 0x01, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   

  // const unsigned char lut_ww[]PROGMEM ={
  IL91874_LUTWW, 42, 
  0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
  0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
  0x10, 0x14, 0x0A, 0x00, 0x00, 0x01,
  0xA0, 0x13, 0x01, 0x00, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  // const unsigned char lut_bw[]PROGMEM ={
  IL91874_LUTBW, 42,
  0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
  0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
  0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,
  0x99, 0x0C, 0x01, 0x03, 0x04, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  // const unsigned char lut_wb[]PROGMEM ={
  IL91874_LUTWB, 42,
  0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
  0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
  0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,
  0x99, 0x0B, 0x04, 0x04, 0x01, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  // const unsigned char lut_bb[]PROGMEM ={
  IL91874_LUTBB, 42,
  0x80, 0x0A, 0x00, 0x00, 0x00, 0x01,
  0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
  0x20, 0x14, 0x0A, 0x00, 0x00, 0x01,
  0x50, 0x13, 0x01, 0x00, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

// clang-format on

class ThinkInk_270_Grayscale4_W3 : public Adafruit_IL91874 {
 private:
 public:
  ThinkInk_270_Grayscale4_W3(int16_t SID, int16_t SCLK, int16_t DC, int16_t RST,
                             int16_t CS, int16_t SRCS, int16_t MISO,
                             int16_t BUSY = -1)
      : Adafruit_IL91874(264, 176, SID, SCLK, DC, RST, CS, SRCS, MISO, BUSY){};

  ThinkInk_270_Grayscale4_W3(int16_t DC, int16_t RST, int16_t CS, int16_t SRCS,
                             int16_t BUSY = -1, SPIClass* spi = &SPI)
      : Adafruit_IL91874(264, 176, DC, RST, CS, SRCS, BUSY, spi){};

  void begin(thinkinkmode_t mode = THINKINK_MONO) {
    Adafruit_IL91874::begin(true);

    setBlackBuffer(0, true); // black defaults to inverted
    setColorBuffer(1, true); // red defaults to not inverted

    if (mode == THINKINK_MONO) {
      _epd_init_code = NULL;
      _epd_lut_code = NULL;
      layer_colors[EPD_WHITE] = 0b00;
      layer_colors[EPD_BLACK] = 0b10;
      layer_colors[EPD_RED] = 0b10;
      layer_colors[EPD_GRAY] = 0b10;
      layer_colors[EPD_LIGHT] = 0b00;
      layer_colors[EPD_DARK] = 0b10;
    }
    if (mode == THINKINK_GRAYSCALE4) {
      _epd_init_code = ti_270w3_gray4_init_code;
      _epd_lut_code = ti_270w3_gray4_lut_code;
      layer_colors[EPD_WHITE] = 0b00;
      layer_colors[EPD_BLACK] = 0b11;
      layer_colors[EPD_RED] = 0b10;
      layer_colors[EPD_GRAY] = 0b10;
      layer_colors[EPD_LIGHT] = 0b10;
      layer_colors[EPD_DARK] = 0b01;
    }

    default_refresh_delay = 1000;
    powerDown();
  };
};

#endif // _THINKINK_270_GRAY4_W3_H
