#include "LedControl.h" //FOR DOT MATRIX 
#include <SPI.h> //FOR SD CARD
#include <SD.h>  //FOR SD CARD
#include <IRremote.h> //FOR IR-REMOTE
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

//FOR LCD SCRN
LiquidCrystal_I2C status(0x27,  16, 2);

//MAXIMUM NUMBER OF MOVEMENTS TRACKED
#define MOVELIMIT 250

//USED FOR MOVEMENT - 
#define leftstep  7
#define rightstep 6
#define leftdir   5
#define rightdir  4

#define vertpin A1
#define horpin A2
#define switchpin 8

//for ON/OFF of LED's
#define ON true
#define OFF false

//Here, 1 is up, 2 is right, 3 is down, 4 is left
int userinput = 0;
int facedir = 4;

//pre declaration of functions (movement)
void step(int direction);
int turn(int direction);

//pre declaration of functions (movement constraints)
int validateinput();

//declaration of function which clears botpath.txt (deletes and creates it again)
void clearbotpath();
//SDCARD PIN
#define SDPIN 10
#define SPI_SPEED SD_SCK_MHZ(4)

//BOT LOCATION
int botloc[2] = {0,0};
int botloctemp[2] = {0, 0};

//SDCARD FILE RELATED
File obstacles;
File botpath;
File checkpoint;
File toxin;

//variables for dot matrix (botpath)
int botpathcolumn, botpathrow;

//variables for dot matrix (OBSTACLES)
int obstacledat[10][2] = {{0,3}, {6,1}, {10,6}, {11,1}, {15,3},{15,6}, {21,4}, {23,1},{26,2},{28,6}};

//variables for dot matrix (checkpoints)
int checkpointdat[4][2] = {{7,7},{15,0},{23,7},{31,0}};
int8_t ischeckpoint = 0;
int chkpntbotpathcolumn, chkpntbotpathrow;
int lastpostemp;
File tempfilebotpath;

//variables for dot matrix (components)
int componentdat[10][2];
int checkpointid;

//USED FOR LED DOT MATRIX DISP
LedControl lc=LedControl(11,13,9,4); 

//IR RECIEVER PIN
#define irpin 3
IRrecv ir(irpin);
decode_results results;
int ircommand = -1;
int hexcodes;

//VARIABLES RELATED TO RECALL 
int rclbotpathcolumn, rclbotpathrow;

//FOR RECALL, predeclaration of few functions
int checkifcheckpoint();
void newbotpath(int id);

//FORWARD DECLARATION OF FUNCTION WHICH BLINKS COORDINATE BOTLOCTEMP n times
void blink(int times);
//FORWARD DECLARATION OF FUNCTION WHICH DISPLAYS BOTPATH
void botpathdisp();


void setup() {
  
  Serial.begin(115200 );

  if (!(SD.begin(SDPIN))){
    while (true){
      Serial.println("222");
    }
  }

  //for LCD
  status.init();
  status.backlight();

  //CREATING REQUIRED TEXT FILES obstacles, botpath, checkpoint and toxin
  obstacles = SD.open("obstacles.txt", FILE_WRITE);
  obstacles.close();
  botpath = SD.open("botpath.txt", FILE_WRITE);
  botpath.print("0 0@");
  botpath.close();
  checkpoint = SD.open("checkpoint.txt",FILE_WRITE);
  checkpoint.close();
  toxin = SD.open("toxin.txt",FILE_WRITE);
  toxin.close();


  pinMode(leftstep,OUTPUT);
  pinMode(rightstep,OUTPUT);
  pinMode(leftdir,OUTPUT);
  pinMode(rightdir,OUTPUT);

  pinMode(vertpin,INPUT);
  pinMode(horpin,INPUT);
  pinMode(switchpin,INPUT);

  for(int i = 0; i < 4; i++){
    lc.shutdown(i,false);
    lc.setIntensity(i,8);
    lc.clearDisplay(i);
  }

  ir.enableIRIn();

}


void loop() {
  
  while (true){
    
    //JOYSTICK INPUT
    if(analogRead(vertpin) > 700) userinput = 1;
    if(analogRead(horpin) < 400) userinput = 2;
    if(analogRead(vertpin) < 400) userinput = 3;
    if(analogRead(horpin) > 700) userinput = 4;
    if((userinput != 0 && validateinput()) ) break;

    }
    
  //CLEARING LCD AS BOT SHOULD'VE MOVED BY NOW
  //lcd.clear();
  Serial.println("CHECKPNT1");
  //resetting ischeckpoint status as now its either that bot is no longer
  //in a checkpoint, or is tasked one of the checkpoint movements

  
  //IR REMOTE CHECKS
  

  //DETERMINE LOCATION OF BOT AFTER MOVEMENT 
  if (userinput == 1){
    botloctemp[0] = botloc[0];
    botloctemp[1] = botloc[1] - 1;
  }

  else if (userinput == 3){
    botloctemp[0] = botloc[0];
    botloctemp[1] = botloc[1] + 1;
  }

  else if (userinput == 2){
    botloctemp[0] = botloc[0] - 1;
    botloctemp[1] = botloc[1];
  }

  else if (userinput == 4){
    botloctemp[0] = botloc[0] + 1;
    botloctemp[1] = botloc[1];
  }
  Serial.println("CHECKING OBSTACLES SECTION");
  //CHECK IF OBSTACLE:
  obstacles = SD.open("obstacle.txt",FILE_WRITE);
  for(int i = 0; i < 10; i++){
    if(obstacledat[i][0] == botloctemp[0] && obstacledat[i][1] == botloctemp[1]){
      
      obstacles.print(String(botloctemp[0]) + " " + String(botloctemp[1]) + "@");
      status.setCursor(0,0);
      status.print("OBSTACLE HIT!");
      blink(2);

      obstacles.close();
      goto endofloop;
    }
  }
  obstacles.close();
  //CHECKPOINT CHECKS:
  Serial.println("STARTING OF MOVEMENT SECTION");
 ;
  //MOVEMENT:
  if ((userinput - facedir )% 2 == 0){
    step(userinput - facedir == 0 ? 1 : 0);
  }
  else{
    if ( userinput - facedir > 0 || userinput - facedir == -3){
      facedir = turn(1);
    }
    else facedir = turn(0);
    step(1);
  }
  //WRITING BOT PATH TO SD
  botpath = SD.open("botpath.txt",FILE_WRITE);
  botpath.print(String(botloc[0]) + " " + String(botloc[1]) + "@");
  botpath.close();

  
  
  
  //LED MATRIX PRINTER
  endofloop:
  botpathdisp();
  
  userinput = 0;
  ircommand = -1;
  delay(300);

}


void step(int direction){

  if (direction){
    digitalWrite(rightdir,HIGH);
    digitalWrite(leftdir,LOW);
    digitalWrite(rightstep,HIGH);
    digitalWrite(leftstep,HIGH);
    delay(10);
    digitalWrite(rightstep,LOW);
    digitalWrite(leftstep,LOW);

  }
  else{
    digitalWrite(rightdir,LOW);
    digitalWrite(leftdir,HIGH);
    digitalWrite(rightstep,HIGH);
    digitalWrite(leftstep,HIGH);
    delay(10);
    digitalWrite(rightstep,LOW);
    digitalWrite(leftstep,LOW);
  }

  if (facedir == 1){
    if(direction){
      botloc[1] = botloc[1] - 1;
    }
    else{
      botloc[1] = botloc[1] + 1;
    }
  }

  else if(facedir == 3){
    if(direction){
      botloc[1] = botloc[1] + 1;
    }
    else{
      botloc[1] = botloc[1] - 1;
    }
  }
  else if (facedir == 2){
    if(direction){
      botloc[0] = botloc[0] - 1;
    }
    else{
      botloc[0] = botloc[0] + 1;
    }
  }
  else if (facedir == 4){
    if(direction){
      botloc[0] = botloc[0] + 1;
    }
    else{
      botloc[0] = botloc[0] - 1;
    }
  }
 //testing of map corners
 /*Serial.println(botloc[0]);
 Serial.println(botloc[1]);
 Serial.println();*/
 
}
int turn(int direction){

  if(direction){
    
    digitalWrite(leftdir,LOW);
    digitalWrite(leftstep,HIGH);
    delay(10);
    digitalWrite(leftstep,LOW);
    
  }

  else{
    digitalWrite(rightdir,LOW);
    digitalWrite(rightstep,HIGH);
    delay(10);
    digitalWrite(rightstep,LOW);
    
  }
  delay(100);
  

return(userinput);
  
}


int validateinput(){

  if (userinput == 1){
    return botloc[1] == 0 ? 0 : 1;
  }

  if (userinput == 3){
    return botloc[1] == 7 ? 0 : 1;
  }
if (userinput == 2){
    return botloc[0] == 0 ? 0 : 1;
  }

  if (userinput == 4){
    return botloc[0] == 31 ? 0 : 1;
  }
}

void blink(int times){
  int DELAY;
  if (times == 1) DELAY = 300;
  else DELAY = 100;
  for(int i = 0; i<4; i++){
    lc.clearDisplay(i);
    //turns all leds off in the dot matrix disp
  }
  for(int i = 0; i< times; i++){
    lc.setLed(botloctemp[0]/8, botloctemp[1], botloctemp[0] % 8,HIGH);
    delay(DELAY);
    lc.setLed(botloctemp[0]/8, botloctemp[1], botloctemp[0] % 8,LOW);
    delay(DELAY);
  }
  botpathdisp();

}

void botpathdisp(){
  botpath = SD.open("botpath.txt",FILE_READ);
  while(botpath.available()){
    while (botpath.peek() >= '0' && botpath.peek() <= '9') {
      botpathcolumn = botpathcolumn * 10 + (botpath.read() - '0');
    }

    if (botpath.peek() == ' ') {
      botpath.read();
    }
    if (botpath.peek() >= '0' && botpath.peek() <= '9') {
      botpathrow = botpath.read() - '0';
    }
    if (botpath.peek() == '@') {
      botpath.read();
    }
    lc.setLed(botpathcolumn / 8, botpathrow, botpathcolumn % 8, true);
    botpathcolumn = 0;
    botpathrow = 0;
  }
  botpath.close();
}


/*void clearbotpath(){
  Serial.println(SD.remove("filename.txt") ? "Success" : "Failed");
  delay(500);
  botpath = SD.open("botpath.txt",FILE_WRITE);
  botpath.print("0 0@");
  botpath.close();
  botloc[0] = 0;
  botloc[1] = 0;

}*/

/*int checkifcheckpoint(){
  checkpoint = SD.open("checkpoint.txt",FILE_READ);
  int tempcheckpoint[10][2];
  int i = 0;

  while (checkpoint.available()){
    tempcheckpoint[i][0] = 0;
    tempcheckpoint[i][1] = 0;
    int checkpointid = 0;
    while(checkpoint.peek() >= '0' && checkpoint.peek() <= '9'){
      tempcheckpoint[i][0] = tempcheckpoint[i][0] * 10 + checkpoint.read() - 48;
    }
    checkpoint.read();
    tempcheckpoint[i][1] = checkpoint.read() - 48;
    checkpoint.read();
    for(int j = 0; j<4; j++){
      if(tempcheckpoint[j][0] == checkpointdat[j][0] && tempcheckpoint[j][1] == checkpointdat[j][1]){
        checkpointid = j;
      }
    }
  }
  return checkpointid;
}*/
/*void newbotpath(int chckpntid){
  int chkcol = checkpointdat[chckpntid][0];
  int chkrow = checkpointdat[chckpntid][1];
  int tempvarcol = 0, tempvarrow = 0;
  int currpos,apos;
  
  
  botpath = SD.open("botpath.txt",FILE_READ);
  while (botpath.available()){
    while(botpath.peek()>= '0' && botpath.peek()<='9'){
      tempvarcol = tempvarcol * 10 + botpath.read() - 48;
    }
    if (botpath.peek() == ' ') botpath.read();
    if(botpath.peek()>= '0' && botpath.peek()<='9'){
      tempvarrow = botpath.read() - 48;
    }
    currpos = botpath.position();
    botpath.read();
    if(tempvarcol == chkcol && tempvarrow == chkrow) apos = currpos;
  }
  botpath.close();
  botpath = SD.open("botpath.txt",FILE_READ);
  while(botpath.available()){
    while(botpath.peek()>= '0' && botpath.peek()<='9'){
      tempvarcol = tempvarcol * 10 + botpath.read() - 48;
    }
    if (botpath.peek() == ' ') botpath.read();
    if(botpath.peek()>= '0' && botpath.peek()<='9'){
      tempvarrow = botpath.read() - 48;
    }
    if(botpath.position() <= apos){
      lc.setLed(tempvarcol/8, tempvarrow, tempvarcol % 8, false);
    }
    else break;
    tempvarcol = 0;
    tempvarrow = 0;
  }
  botpath.close();
  botpath = SD.open("botpath.txt",FILE_READ);
  tempfilebotpath = SD.open("botpathtemp.txt",FILE_WRITE);
  for(int i=0; i<=apos;i++){
    
    tempfilebotpath.print(botpath.read());

  }
  botpath.close();
  tempfilebotpath.close();
  SD.remove("botpath.txt");
  botpath = SD.open("botpath.txt",FILE_WRITE);
  tempfilebotpath = SD.open("botpathtemp.txt",FILE_READ);
  while(tempfilebotpath.available()){
    botpath.print(tempfilebotpath.read());
  }

}*/

void newbotpath(int chckpntid) {
  int chkcol = checkpointdat[chckpntid][0];
  int chkrow = checkpointdat[chckpntid][1];
  int tempvarcol = 0, tempvarrow = 0;
  int currpos = 0, apos = -1;

  // 1st pass: Find position where checkpoint appears
  botpath = SD.open("botpath.txt", FILE_READ);
  while (botpath.available()) {
    tempvarcol = 0;
    tempvarrow = 0;

    // Read column
    while (botpath.peek() >= '0' && botpath.peek() <= '9') {
      tempvarcol = tempvarcol * 10 + botpath.read() - '0';
    }

    if (botpath.peek() == ' ') botpath.read(); // Skip space

    // Read row
    if (botpath.peek() >= '0' && botpath.peek() <= '9') {
      tempvarrow = botpath.read() - '0';
    }

    currpos = botpath.position();  // Save position AFTER full coordinate
    botpath.read(); // Skip '@'

    // If match, store position
    if (tempvarcol == chkcol && tempvarrow == chkrow) {
      apos = currpos;
    }
  }
  botpath.close();

  if (apos == -1) return; // Checkpoint not found, exit early

  // 2nd pass: Turn off LEDs after checkpoint
  botpath = SD.open("botpath.txt", FILE_READ);
  while (botpath.available()) {
    tempvarcol = 0;
    tempvarrow = 0;

    while (botpath.peek() >= '0' && botpath.peek() <= '9') {
      tempvarcol = tempvarcol * 10 + botpath.read() - '0';
    }

    if (botpath.peek() == ' ') botpath.read();

    if (botpath.peek() >= '0' && botpath.peek() <= '9') {
      tempvarrow = botpath.read() - '0';
    }

    if (botpath.position() <= apos) {
      lc.setLed(tempvarcol / 8, tempvarrow, tempvarcol % 8, false);
    } else {
      break;
    }

    botpath.read(); // skip '@'
  }
  botpath.close();

  // 3rd pass: Copy up to apos into new file
  botpath = SD.open("botpath.txt", FILE_READ);
  tempfilebotpath = SD.open("botpathtemp.txt", FILE_WRITE);
  for (int i = 0; i < apos; i++) {
    tempfilebotpath.write(botpath.read());
  }
  botpath.close();
  tempfilebotpath.close();

  // Replace original file
  SD.remove("botpath.txt");
  tempfilebotpath = SD.open("botpathtemp.txt", FILE_READ);
  botpath = SD.open("botpath.txt", FILE_WRITE);
  while (tempfilebotpath.available()) {
    botpath.write(tempfilebotpath.read());
  }
  tempfilebotpath.close();
  botpath.close();
}
A4988
A4988
LEFT MOTOR
RIGHT MOTOR