volatile long endTime = 0;
volatile boolean InteruptTriggered = false;
long startTime = 0;
long lasttest = 0;
long microsDelta;
boolean wireIn = 0;
boolean oldWireIn = 0;
boolean newSerialData = false;
boolean waitingForBluetoothData = true;
boolean delayInMillis = true;
boolean configured = false;
boolean waitingForInterupt = false;
//String holds Text
String newestString;
//int holds numbers
int delayOn = 0;
int delayOff = 0;
int mode = 0;

void setup() {
  Serial.begin(9600);
  Serial3.begin(57600);
  attachInterrupt(0, ISRroutine, CHANGE);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(A0, OUTPUT);
  pinMode(10, OUTPUT);
  PORTB = 0b00000000;
  digitalWrite(A0, LOW);


}

void loop() {
  do {
    PORTB = 0b00000000;
    waitingForInterupt = false;
    if (configured) {
      digitalWrite (11, HIGH);
    }
    digitalWrite (10, HIGH);
    mode = waitForIntParameter ("mode", 4, 1);
    PORTB = 0b00000000;
    if (mode == 1) {
      PORTB = 0b00000000;
      digitalWrite (11, HIGH);
      analogWrite (13, 200);
      delayOn = waitForIntParameter ("Ton", 3, 1); 
      delayOff = waitForIntParameter ("Toff", 4, 1 );
      delayInMillis = waitForIntParameter ("millis", 6, 1);
      configured = true;
      PORTB = 0b00000000;
    }
    else if (mode == 2) {
           PORTB = 0b00000000;
      int pwmDutyCycle = 0;
           do {
        pwmDutyCycle = waitForIntParameter ("pwm", 3 , 0);
        analogWrite (12, pwmDutyCycle);
        analogWrite (11, pwmDutyCycle);
      } while (pwmDutyCycle != 256);
      PORTB = 0b00000000;
    }
    else if (mode == 3) {
      PORTB = 0b00000000;
      if (digitalRead (2) == HIGH && configured) {
        InteruptTriggered = false;
        waitingForInterupt = true;
        startTime = micros();
        if (delayInMillis) {
          while (!InteruptTriggered) {
            delay (delayOff);
            PORTB = 0b11000000;
            delay (delayOn);
            PORTB = 0b00000000;
          }
        }
        else {
          while (!InteruptTriggered) {
            delayMicroseconds (delayOff);
            PORTB = 0b11000000;
            delayMicroseconds (delayOn);
            PORTB = 0b00000000;
          }
        }
        PORTB = 0b00000000;
        waitingForInterupt = false;
        delay (100);
        microsDelta = (endTime - startTime);
        Serial3.print ("r-");
        Serial3.print (microsDelta);
        delay (100);
      else {
        delay (50);
        Serial3.print ("nc");
        delay (50);
        Serial3.print ("r-0000000");
        for (int a = 0; a < 7; a++) {
          digitalWrite (13, HIGH);
          delay (75);
          digitalWrite (13, LOW);
          digitalWrite (11, HIGH);
          delay (150);
          digitalWrite (11, LOW);
          digitalWrite (10, HIGH);
          delay (225);
          digitalWrite (10, LOW);
        }



      }
    }
    else if (mode == 4) {
      do {
        int pins[] = {13, 11, 10};
        int num1  = random (0, 3);
        digitalWrite (10, LOW);
        digitalWrite (11, LOW);
        digitalWrite (13, LOW);

        for (int i = 0; i < 255 && !newSerialData; i++) {
          analogWrite (pins[num1], i);
          delay (5);
          serialEvent3();
        }

        for (int i = 255; i > 0 && !newSerialData; i--) {
          analogWrite (pins[num1], i);
          delay (5);
          serialEvent3();
        }
      } while (!newSerialData);
    }
  } while (true);
}

int waitForIntParameter (String term, int termLength, boolean sendWireStatus) {
  int parameter = -1;
  while (!newSerialData) {
    serialEvent3();
    if (millis() - lasttest > 400 ) {
      if (sendWireStatus) {
        digitalWrite (12, HIGH);
        delayMicroseconds(10);
        wireIn = digitalRead(2);
        digitalWrite (12, LOW);
        lasttest = millis();
      }
      else {
        wireIn = true;
      }
      if (wireIn) {
        delay (30);
        Serial3.println("c");
        delay (30);
      }
      else {
        delay (30);
        Serial3.println("n");
        delay (30);
      }
    }
  }
  newSerialData = false;
  if ((newestString.substring(0, termLength)).equals(term)) {
    parameter = (newestString.substring(termLength)).toInt();
  }
  return parameter;
}
void ISRroutine () {
  endTime = micros();
  if (waitingForInterupt) {
    InteruptTriggered = true;
    PORTB = 0b00000000;
  }
  else {
    InteruptTriggered = false;
  }
}
void serialEvent3() {
  if (Serial3.available()) {
    newestString = parseInput(serialRead());
    newSerialData = true;

  }
}
String serialRead () {
  String finalString = "";
  finalString.reserve(52);
  while (Serial3.available() > 0)
  {
    finalString += (char)Serial3.read();
    delay (1);
  }
  return finalString;
}

String parseInput (String Input) {
  Input.trim();
  String output;
  int stringLength = (Input.substring(0, Input.indexOf ("@<@"))).toInt();
  output = Input.substring ( (Input.indexOf ("@<@") + 3), stringLength + Input.indexOf ("@<@") + 3  );
  return output;

}