#include <MCUFRIEND_kbv.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <TouchScreen.h>
#include <SD.h>

#if defined(__SAM3X8E__)
#undef __FlashStringHelper::F(string_literal)
#define F(string_literal) string_literal
#endif

// wiring with UNO or Mega2560:
//--------------POWER Pins--------------------------------
//   5V  connects to DC 5V
//   GND connects to Ground
//   3V3 do not need to connect(NC)
//--------------LCD Display Pins--------------------------
//   LCD_RD   connects to Analog pin A0
//   LCD_WR   connects to Analog pin A1
//   LCD_RS   connects to Analog pin A2
//   LCD_CS   connects to Analog pin A3
//   LCD_RST  connects to Analog pin A4
//   LCD_D0   connects to digital pin 8
//   LCD_D1   connects to digital pin 9
//   LCD_D2   connects to digital pin 2
//   LCD_D3   connects to digital pin 3
//   LCD_D4   connects to digital pin 4
//   LCD_D5   connects to digital pin 5
//   LCD_D6   connects to digital pin 6
//   LCD_D7   connects to digital pin 7
//--------------SD-card fuction Pins ----------------------
//This Connection Only for UNO, Do not support Mega2560
//because they use different Hardware-SPI Pins
//SD_SS    connects to digital pin 10
//SD_DI    connects to digital pin 11
//SD_DO    connects to digital pin 12
//SD_SCK   connects to digital pin 13

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
#define LCD_CS A3   // Chip Select goes to Analog 3
#define LCD_CD A2  // Command/Data goes to Analog 2
#define LCD_WR A1  // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define YP A3  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 9   // can be a digital pin
#define XP 8   // can be a digital pin

//Param For 3.5"
#define TS_MINX 118
#define TS_MAXX 906

#define TS_MINY 92
#define TS_MAXY 951
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);


// Assign human-readable names to some common 16-bit color values:
#define	BLACK   0x0000
#define	BLUE    0x001F
#define	RED     0xF800
#define	GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
#define BRAUN   0x8A22
#define BLUB    0xF52C
//#define


// 0xFFc1c1 = 11110 101001 01100 -> F52C

MCUFRIEND_kbv tft;

#define BOXSIZE 26
#define RADIUS ((BOXSIZE-4)/2)
#define PENRADIUS 2

int oldcolor, currentcolor;

int filenumber=0;

void setup(void) {
  Serial.begin(9600);
  Serial.println(F("TFT LCD test"));

  pinMode(10, OUTPUT);
  if (!SD.begin(10)) {
    tft.fillScreen(RED);
    while (1);
  }

  tft.reset();

  uint16_t identifier = tft.readID();
  /*if (identifier == 0x9325) {
    Serial.println(F("Found ILI9325 LCD driver"));
  } else if (identifier == 0x9328) {
    Serial.println(F("Found ILI9328 LCD driver"));
  } else if (identifier == 0x4535) {
    Serial.println(F("Found LGDP4535 LCD driver"));
  } else if (identifier == 0x7575) {
    Serial.println(F("Found HX8347G LCD driver"));
  } else if (identifier == 0x9595) {
    Serial.println(F("Found HX8347-I LCD driver"));
  } else if (identifier == 0x4747) {
    Serial.println(F("Found HX8347-D LCD driver"));
  } else if (identifier == 0x8347) {
    Serial.println(F("Found HX8347-A LCD driver"));
  } else if (identifier == 0x9341) {
    Serial.println(F("Found ILI9341 LCD driver"));
  } else if (identifier == 0x7783) {
    Serial.println(F("Found ST7781 LCD driver"));
  } else if (identifier == 0x8230) {
    Serial.println(F("Found UC8230 LCD driver"));
  } else if (identifier == 0x8357) {
    Serial.println(F("Found HX8357D LCD driver"));
  } else if (identifier == 0x0101) {
    identifier = 0x9341;
    Serial.println(F("Found 0x9341 LCD driver"));
  } else if (identifier == 0x7793) {
    Serial.println(F("Found ST7793 LCD driver"));
  } else if (identifier == 0xB509) {
    Serial.println(F("Found R61509 LCD driver"));
  } else if (identifier == 0x9486) {
    Serial.println(F("Found ILI9486 LCD driver"));
  } else if (identifier == 0x9488) {
    Serial.println(F("Found ILI9488 LCD driver"));
  } else {
    Serial.print(F("Unknown LCD driver chip: "));
    Serial.println(identifier, HEX);
    Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:"));
    Serial.println(F("  #define USE_ADAFRUIT_SHIELD_PINOUT"));
    Serial.println(F("should appear in the library header (Adafruit_TFT.h)."));
    Serial.println(F("If using the breakout board, it should NOT be #defined!"));
    Serial.println(F("Also if using the breakout, double-check that all wiring"));
    Serial.println(F("matches the tutorial."));
    identifier = 0x9488;
  }*/
  tft.begin(identifier);

  tft.fillScreen(BLACK);

  tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
  tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
  tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, GREEN);
  tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, CYAN);
  tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, BLUE);
  tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, MAGENTA);
  tft.fillRect(BOXSIZE * 6, 0, BOXSIZE, BOXSIZE, BRAUN);
  tft.fillRect(BOXSIZE * 7, 0, BOXSIZE, BOXSIZE, WHITE);
  tft.fillRect(BOXSIZE * 8, 0, BOXSIZE, BOXSIZE, BLUB);
  tft.fillRect(BOXSIZE * 9, 0, BOXSIZE, BOXSIZE, BLACK);
  //tft.drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color,
  tft.fillCircle(BOXSIZE * 10 + BOXSIZE / 2, BOXSIZE / 2, RADIUS, WHITE);

  tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
  currentcolor = RED;

  pinMode(13, OUTPUT);
}

#define MINPRESSURE 10
#define MAXPRESSURE 1000

void speichern(String name) {
  int x;
  int y;
  uint16_t pixel;
  uint16_t farbe = WHITE;

  File myFile = SD.open(name, O_WRITE | O_CREAT);

  if (myFile) {
    Serial.print("Writing to ");
    Serial.println(name);

    myFile.println("P6");
    myFile.print(tft.width());
    myFile.print(" ");
    myFile.print(tft.height());
    myFile.println(" 255");

    for (y = tft.height() - 1; y >= BOXSIZE; y--) {
      //Serial.print(" y=");
      //Serial.println(y);

      if (y % 6 == 0) {
        if (farbe == WHITE) {
          farbe = BLACK;
        } else {
          farbe = WHITE;
        }
        tft.fillCircle(BOXSIZE * 10 + BOXSIZE / 2, BOXSIZE / 2, RADIUS, farbe);
      }

      for (x = tft.width()-1; x >= 0; x--) {
        pixel = tft.readPixel(x, y);
        unsigned char red   = (pixel & 0xF800) >> 8;
        unsigned char green = (pixel & 0x7E0) >> 3;
        unsigned char blue  = (pixel & 0x1F) << 3;

       /* if (pixel != 0)
        {
          Serial.print("pix=");
          Serial.print(pixel);
          Serial.print("  red=");
          Serial.print(red);
          Serial.print("  green=");
          Serial.print(green);
          Serial.print("  blue=");
          Serial.println(blue);
        }
        */
        
        myFile.write(green);
        myFile.write(blue);
        myFile.write(red);
      }
    }

    myFile.close();
  }
  tft.fillCircle(BOXSIZE * 10 + BOXSIZE / 2, BOXSIZE / 2, RADIUS, WHITE);
}


void loop()
{
  digitalWrite(13, HIGH);
  TSPoint p = ts.getPoint();
  digitalWrite(13, LOW);

  // if sharing pins, you'll need to fix the directions of the touchscreen pins
  //pinMode(XP, OUTPUT);
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  //pinMode(YM, OUTPUT);

  // we have some minimum pressure we consider 'valid'
  // pressure of 0 means no pressing!

  if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {

    /*Serial.print("X = "); Serial.print(p.x);
    Serial.print("\tY = "); Serial.print(p.y);
    Serial.print("\tPressure = "); Serial.println(p.z);
    */
    
    p.x = tft.width() - map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
    p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0);
    //p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
    //p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0);

    if (p.y < BOXSIZE) {
      oldcolor = currentcolor;

      if (p.x < BOXSIZE) {
        currentcolor = RED;
        tft.drawRect(0 + 1, 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
      } else if (p.x < BOXSIZE * 2) {
        currentcolor = YELLOW;
        tft.drawRect(BOXSIZE, 0, BOXSIZE - 2, BOXSIZE - 2, BRAUN);
      } else if (p.x < BOXSIZE * 3) {
        currentcolor = GREEN;
        tft.drawRect(BOXSIZE * 2 + 1, 1, BOXSIZE - 2, BOXSIZE - 2, RED);
      } else if (p.x < BOXSIZE * 4) {
        currentcolor = CYAN;
        tft.drawRect(BOXSIZE * 3 + 1, 1, BOXSIZE - 2, BOXSIZE - 2, RED);
      } else if (p.x < BOXSIZE * 5) {
        currentcolor = BLUE;
        tft.drawRect(BOXSIZE * 4 + 1, 1, BOXSIZE - 2, BOXSIZE - 2, RED);
      } else if (p.x < BOXSIZE * 6) {
        currentcolor = MAGENTA;
        tft.drawRect(BOXSIZE * 5 + 1, 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
      } else if (p.x < BOXSIZE * 7) {
        currentcolor = BRAUN;
        tft.drawRect(BOXSIZE * 6 + 1, 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
      } else if (p.x < BOXSIZE * 8) {
        currentcolor = WHITE;
        tft.drawRect(BOXSIZE * 7 + 1, 1, BOXSIZE - 2, BOXSIZE - 2, BLUE);
      } else if (p.x < BOXSIZE * 9) {
        currentcolor = BLUB;
        tft.drawRect(BOXSIZE * 8 + 1, 1, BOXSIZE - 2, BOXSIZE - 2, BLUE);
      } else if (p.x < BOXSIZE * 10) {
        currentcolor = BLACK;
        tft.drawRect(BOXSIZE * 9 + 1, 1, BOXSIZE - 2, BOXSIZE - 2, WHITE);
      } else if (p.x < BOXSIZE * 11) {
        String fname;
        int existiert=1;
        while(existiert==1)
        {
            fname = "test";
            fname = fname + filenumber +".ppm";
            File myFile = SD.open(fname, O_READ);
            if(myFile)
            {
              myFile.close();
              filenumber++;
            }
            else
            {
              existiert=0;
            }
        }
        Serial.println(fname);
        speichern(fname);
      } else {
        Serial.println("erase");
        tft.fillRect(0, BOXSIZE, tft.width(), tft.height() - BOXSIZE, currentcolor);
      }

      if (oldcolor != currentcolor) {
        if (oldcolor == RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
        if (oldcolor == YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
        if (oldcolor == GREEN) tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, GREEN);
        if (oldcolor == CYAN) tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, CYAN);
        if (oldcolor == BLUE) tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, BLUE);
        if (oldcolor == MAGENTA) tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, MAGENTA);
        if (oldcolor == BRAUN) tft.fillRect(BOXSIZE * 6, 0, BOXSIZE, BOXSIZE, BRAUN);
        if (oldcolor == WHITE) tft.fillRect(BOXSIZE * 7, 0, BOXSIZE, BOXSIZE, WHITE);
        if (oldcolor == BLUB) tft.fillRect(BOXSIZE * 8, 0, BOXSIZE, BOXSIZE, BLUB);
        if (oldcolor == BLACK) tft.fillRect(BOXSIZE * 9, 0, BOXSIZE, BOXSIZE, BLACK);
      }
    }
    if (((p.y - PENRADIUS) > BOXSIZE) && ((p.y + PENRADIUS) < tft.height())) {
      tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
    }
  }
}