/***************************************************
  This is our touchscreen painting example for the Adafruit ILI9341
  captouch shield
  ----> http://www.adafruit.com/products/1947

  Check out the links above for our tutorials and wiring diagrams

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/

//240*320

#include <Adafruit_GFX.h> // Core graphics library
#include <SPI.h>          // this is needed for display
#include <Adafruit_ILI9341.h>
#include <Wire.h> // this is needed for FT6206
#include <Adafruit_FT6206.h>
// #include <ListLib.h>

// The FT6206 uses hardware I2C (SCL/SDA)
Adafruit_FT6206 ctp = Adafruit_FT6206();

// The display also uses hardware SPI, plus #9 & #10
#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

// define colors
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define WHITE 0xFFFF

//define variables

int currentScreen = 0; 
// 0 = StartOS screen
// 1 = Home screen
int screenToLoad = 0;

class Button
{

public:
  int x;
  int y;
  int xLength;
  int yLength;
  String text;
  double textSize;
  int borderSize;
  uint16_t borderColor;
  uint16_t fillColor;
  uint16_t textColor;
  uint16_t selectedColor;
  bool selected = true; //true = buttonpressed
  int redirectTo;

  Button()
  {
  }

  Button(int x, int y, int xLength, int yLength, String text, double textSize, int borderSize, uint16_t borderColor, uint16_t fillColor, uint16_t textColor, uint16_t selectedColor,int redirectTo)
      : x(x), y(y), xLength(xLength), yLength(yLength), text(text), textSize(textSize), borderSize(borderSize), borderColor(borderColor), fillColor(fillColor), textColor(textColor), selectedColor(selectedColor), redirectTo(redirectTo)
  {
  }

  bool drawButton(int xTouch, int yTouch)
  {
    bool output = false;
    if (x <= xTouch && x + xLength >= xTouch && y <= yTouch && y + yLength >= yTouch)
    {
      output = true;
      if (!selected)
      {
        tft.fillRect(x, y, xLength, yLength, borderColor);
        tft.fillRect(x + borderSize, y + borderSize, xLength - borderSize * 2, yLength - borderSize * 2, selectedColor);
        selected = true; 
      }
    }
    else if(selected)
    {
      tft.fillRect(x, y, xLength, yLength, borderColor);
      tft.fillRect(x + borderSize, y + borderSize, xLength - borderSize * 2, yLength - borderSize * 2, fillColor);
      selected  = false;
    }

    tft.setCursor(x + ((xLength - text.length() * 6 * textSize) / 2), y + (yLength - textSize * 8) / 2); // text size change per text size
    tft.setTextColor(textColor);
    tft.setTextSize(textSize);
    tft.print(text);
    return output;
  }

  bool equals(Button other)
  {
    return (x == other.x &&
            y == other.y &&
            xLength == other.xLength &&
            yLength == other.yLength &&
            text == other.text &&
            textSize == other.textSize &&
            borderColor == other.borderColor &&
            fillColor == other.fillColor &&
            textColor == other.textColor &&
            selectedColor == other.selectedColor);
  }
};

class ButtonList
{
public:
  byte nextFreePos = 0;
  Button data[16];
  ButtonList()
  {
  }
  void add(Button button)
  {
    if (nextFreePos <= 15)
    {
      data[nextFreePos] = button;
      nextFreePos++;
    }
  }
  void remove(Button button)
  {
    if (nextFreePos > 0)
    {
      for (byte i = 0; i <= nextFreePos - 1; i++)
      {
        if (data[i].equals(button))
        {
          for (byte k = i; k <= nextFreePos - 1; k++)
          {
            if (k < nextFreePos - 2)
            {
              data[k] = data[k + 1];
            }
          }
          break;
        }
      }
      nextFreePos--;
    }
  }
  void clear() {
    nextFreePos = 0;
  }

  byte count()
  {
    return nextFreePos;
  }
};

ButtonList displayedButtons;

void renderButtons(int touchX, int touchY)
{
  for (byte i = 0; i < displayedButtons.count(); i++)
  {
    if(displayedButtons.data[i].drawButton(touchX, touchY)){
      screenToLoad = displayedButtons.data[i].redirectTo;
    }
  }
}

void setup(void)
{
  Serial.begin(115200);
  while (!Serial)
    delay(10); // pause the serial port

  Serial.println(F("Cap Touch Paint!"));

  tft.begin();

  tft.fillScreen(BLACK);
  tft.setCursor(15, 160);
  tft.setTextSize(4);
  tft.setTextColor(WHITE);
  tft.println("Touch1001");
  tft.setTextSize(1);
  tft.setTextColor(WHITE);
  tft.println("Initilazing Touchscreen");

  if (!ctp.begin(40, &Wire))
  { // pass in 'sensitivity' coefficient and I2C bus
    Serial.println("Couldn't start FT6206 touchscreen controller");
    tft.setTextColor(RED);
    tft.println("Couldn't start FT6206 touchscreen controller");
    while (1)
      delay(10);
  }

  Serial.println("Capacitive touchscreen started");
  delay(1000);

  Serial.println("delay done, printing buttons");

  Button contButton(60, 220, 120, 40, "start OS", 2, 2, WHITE, BLACK, GREEN, RED,1);

  displayedButtons.add(contButton);
  renderButtons(999,999);
  Serial.println("setup done");
}

void loop()
{
  if(screenToLoad != currentScreen) {
    displayedButtons.clear();
    tft.fillScreen(BLACK);
    if(screenToLoad == 1) {
      Button calcAppButton(10, 290, 40, 40, "", 1, 2, WHITE, BLACK, GREEN, WHITE, 2);
      displayedButtons.add(calcAppButton);
      Serial.println("screenDoneLoading");
    }
    
    currentScreen = screenToLoad;
  }

  // Wait for a touch
  if (ctp.touched())
  {
    // Retrieve a point
    TS_Point p = ctp.getPoint();

    // flip it around to match the screen.
    p.x = map(p.x, 0, 240, 240, 0);
    p.y = map(p.y, 0, 320, 320, 0);
    renderButtons(p.x, p.y);
  }
  else {
    renderButtons(999,999);
  }
  delay(100);
}