
#include "Arduino.h"

#ifdef ROO_TESTING

#include "roo_testing/devices/display/st77xx/st77xx.h"
#include "roo_testing/microcontrollers/esp32/fake_esp32.h"
#include "roo_testing/transducers/ui/viewport/flex_viewport.h"
#include "roo_testing/transducers/ui/viewport/fltk/fltk_viewport.h"

using roo_testing_transducers::FlexViewport;
using roo_testing_transducers::FltkViewport;

struct Emulator {
  FltkViewport viewport;
  FlexViewport flexViewport;

  FakeSt77xxSpi display;

  Emulator()
      : viewport(), flexViewport(viewport, 2), display(flexViewport, 240, 240) {
    FakeEsp32().attachSpiDevice(display, 18, 19, 23);
    FakeEsp32().gpio.attachOutput(5, display.cs());
    FakeEsp32().gpio.attachOutput(2, display.dc());
    FakeEsp32().gpio.attachOutput(4, display.rst());
  }
} emulator;

#endif

#include <string>

#include "roo_backport.h"
#include "roo_backport/string_view.h"
#include "roo_display.h"
#include "roo_display/font/font.h"
#include "roo_display/shape/basic.h"
#include "roo_display/ui/text_label.h"
#include "roo_fonts/NotoSansMono_Regular/10.h"
#include "roo_fonts/NotoSansMono_Regular/12.h"
#include "roo_fonts/NotoSansMono_Regular/15.h"
#include "roo_fonts/NotoSansMono_Regular/18.h"
#include "roo_fonts/NotoSansMono_Regular/27.h"
#include "roo_fonts/NotoSansMono_Regular/40.h"
#include "roo_fonts/NotoSansMono_Regular/60.h"
#include "roo_fonts/NotoSansMono_Regular/8.h"
#include "roo_fonts/NotoSansMono_Regular/90.h"
#include "roo_fonts/NotoSans_Bold/10.h"
#include "roo_fonts/NotoSans_Bold/12.h"
#include "roo_fonts/NotoSans_Bold/15.h"
#include "roo_fonts/NotoSans_Bold/18.h"
#include "roo_fonts/NotoSans_Bold/27.h"
#include "roo_fonts/NotoSans_Bold/40.h"
#include "roo_fonts/NotoSans_Bold/60.h"
#include "roo_fonts/NotoSans_Bold/8.h"
#include "roo_fonts/NotoSans_Bold/90.h"
#include "roo_fonts/NotoSans_Regular/10.h"
#include "roo_fonts/NotoSans_Regular/12.h"
#include "roo_fonts/NotoSans_Regular/15.h"
#include "roo_fonts/NotoSans_Regular/18.h"
#include "roo_fonts/NotoSans_Regular/27.h"
#include "roo_fonts/NotoSans_Regular/40.h"
#include "roo_fonts/NotoSans_Regular/60.h"
#include "roo_fonts/NotoSans_Regular/8.h"
#include "roo_fonts/NotoSans_Regular/90.h"
#include "roo_fonts/NotoSerif_Italic/10.h"
#include "roo_fonts/NotoSerif_Italic/12.h"
#include "roo_fonts/NotoSerif_Italic/15.h"
#include "roo_fonts/NotoSerif_Italic/18.h"
#include "roo_fonts/NotoSerif_Italic/27.h"
#include "roo_fonts/NotoSerif_Italic/40.h"
#include "roo_fonts/NotoSerif_Italic/60.h"
#include "roo_fonts/NotoSerif_Italic/8.h"
#include "roo_fonts/NotoSerif_Italic/90.h"

using namespace roo_display;

// Change these two lines to use a different driver, transport, or pins.
#include "roo_display/driver/st7789.h"
St7789spi_240x240<5, 2, 4> device;

Display display(device);

struct FontFamily {
  FontFamily(const Font& f8, const Font& f10, const Font& f12, const Font& f15,
             const Font& f18, const Font& f27, const Font& f40, const Font& f60,
             const Font& f90)
      : f8(f8),
        f10(f10),
        f12(f12),
        f15(f15),
        f18(f18),
        f27(f27),
        f40(f40),
        f60(f60),
        f90(f90) {}

  const Font& f8;
  const Font& f10;
  const Font& f12;
  const Font& f15;
  const Font& f18;
  const Font& f27;
  const Font& f40;
  const Font& f60;
  const Font& f90;
};

FontFamily notoSansRegular(
    font_NotoSans_Regular_8(), font_NotoSans_Regular_10(),
    font_NotoSans_Regular_12(), font_NotoSans_Regular_15(),
    font_NotoSans_Regular_18(), font_NotoSans_Regular_27(),
    font_NotoSans_Regular_40(), font_NotoSans_Regular_60(),
    font_NotoSans_Regular_90());

FontFamily notoSansBold(font_NotoSans_Bold_8(), font_NotoSans_Bold_10(),
                        font_NotoSans_Bold_12(), font_NotoSans_Bold_15(),
                        font_NotoSans_Bold_18(), font_NotoSans_Bold_27(),
                        font_NotoSans_Bold_40(), font_NotoSans_Bold_60(),
                        font_NotoSans_Bold_90());

FontFamily notoSerifItalic(
    font_NotoSerif_Italic_8(), font_NotoSerif_Italic_10(),
    font_NotoSerif_Italic_12(), font_NotoSerif_Italic_15(),
    font_NotoSerif_Italic_18(), font_NotoSerif_Italic_27(),
    font_NotoSerif_Italic_40(), font_NotoSerif_Italic_60(),
    font_NotoSerif_Italic_90());

FontFamily notoSansMonoRegular(
    font_NotoSansMono_Regular_8(), font_NotoSansMono_Regular_10(),
    font_NotoSansMono_Regular_12(), font_NotoSansMono_Regular_15(),
    font_NotoSansMono_Regular_18(), font_NotoSansMono_Regular_27(),
    font_NotoSansMono_Regular_40(), font_NotoSansMono_Regular_60(),
    font_NotoSansMono_Regular_90());

void setup() {
  Serial.begin(9600);
  SPI.begin();  // Use default SPI pins, or specify your own here.
  display.init(color::Gainsboro);
}

int16_t printLn(DrawingContext& dc, const Font& font, int16_t x, int16_t y,
                roo::string_view text, Color color) {
  dc.draw(StringViewLabel(text, font, color, FillMode::kExtents), x,
          y + font.metrics().glyphYMax());
  return font.metrics().linespace() + 1;
}

void printText(const FontFamily& fonts) {
  DrawingContext dc(display);
  dc.fill(color::Gainsboro);
  int16_t y = 1;
  const char* text = "Zażółć gęślą jaźń 12345.67890 !@#$%^&*()";
  Color color = color::Black;
  dc.setBackgroundColor(color::BlanchedAlmond);
  y += printLn(dc, fonts.f8, 10, y, text, color);
  dc.setBackgroundColor(color::OldLace);
  y += printLn(dc, fonts.f10, 10, y, text, color);
  dc.setBackgroundColor(color::LemonChiffon);
  y += printLn(dc, fonts.f12, 10, y, text, color);
  dc.setBackgroundColor(color::Bisque);
  y += printLn(dc, fonts.f15, 10, y, text, color);
  dc.setBackgroundColor(color::Beige);
  y += printLn(dc, fonts.f18, 10, y, text, color);
  dc.setBackgroundColor(color::PapayaWhip);
  y += printLn(dc, fonts.f27, 10, y, text, color);
  dc.setBackgroundColor(color::PowderBlue);
  y += printLn(dc, fonts.f40, 10, y, text, color);
  dc.setBackgroundColor(color::LightGreen);
  y += printLn(dc, fonts.f60, 10, y, text, color);
  dc.setBackgroundColor(color::MistyRose);
  y += printLn(dc, fonts.f90, 10, y, text, color);
  delay(1000);
}

void loop() {
  // Sans serif fonts.
  printText(notoSansRegular);
  printText(notoSansBold);
  // Serif fonts.
  printText(notoSerifItalic);
  // Monotype font.
  printText(notoSansMonoRegular);
}
