// FW_VERSION informativo — no hace OTA, se flashea por USB
#define FW_VERSION 20
#include <Servo.h>

// ==== Pines motores ====
const int ENA = D1;
const int ENB = D5;
const int IN1 = D6;
const int IN2 = D7;
const int IN3 = D2;
const int IN4 = D0;

// ==== Pines servos ====
const int SERVO_X_PIN = D3;
const int SERVO_Y_PIN = D4;

// ==== Pin buzzer ====
const int buzzerPin = D8;

Servo servoX;
Servo servoY;

int currentSpeed = 150;
int posX = 90;
int posY = 90;

bool espReady = false;

void setup() {
  // 1. Motores parados inmediatamente
  pinMode(ENA, OUTPUT); pinMode(ENB, OUTPUT);
  pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);
  stopMotors();

  // 2. Serial
  Serial.begin(9600);

  // 3. Periféricos
  analogWriteRange(255);
  analogWriteFreq(1000);
  servoX.attach(SERVO_X_PIN);
  servoY.attach(SERVO_Y_PIN);
  pinMode(buzzerPin, OUTPUT);
  servoX.write(posX);
  servoY.write(posY);

  // 4. Esperar a que el ESP32-CAM termine de arrancar (~20s)
  // El ESP32 necesita: WiFiManager + OTA check + arrancar servidor
  unsigned long elapsed = millis();
  if (elapsed < 20000) delay(20000 - elapsed);

  // 5. Descartar cualquier basura que haya llegado por Serial durante el arranque
  while (Serial.available()) Serial.read();

  // 6. Listo — 2 pitidos
  for (int i = 0; i < 2; i++) {
    digitalWrite(buzzerPin, HIGH); delay(180);
    digitalWrite(buzzerPin, LOW);  delay(180);
  }
  espReady = true;
}

// Watchdog: si no llega comando de movimiento en 1.5s → para motores
unsigned long lastMoveMs = 0;
bool motorRunning = false;

void loop() {
  if (motorRunning && (millis() - lastMoveMs > 1500)) {
    stopMotors();
    motorRunning = false;
  }

  if (!Serial.available()) return;
  char c = Serial.read();

  if (!espReady) return;

  if      (c == 'F') { forward();    lastMoveMs = millis(); motorRunning = true; }
  else if (c == 'B') { backward();   lastMoveMs = millis(); motorRunning = true; }
  else if (c == 'L') { left();       lastMoveMs = millis(); motorRunning = true; }
  else if (c == 'R') { right();      lastMoveMs = millis(); motorRunning = true; }
  else if (c == 'S') { stopMotors(); motorRunning = false; }
  else if (c == 'V') {
    int val = Serial.parseInt();
    if (val >= 0 && val <= 255) currentSpeed = val;
  }
  else if (c == 'X') {
    int val = Serial.parseInt();
    if (val >= 0 && val <= 180) { posX = val; servoX.write(posX); }
  }
  else if (c == 'Y') {
    int val = Serial.parseInt();
    if (val >= 0 && val <= 180) { posY = val; servoY.write(posY); }
  }
  else if (c == 'H') {
    int val = Serial.parseInt();
    digitalWrite(buzzerPin, val > 0 ? HIGH : LOW);
  }
}

// ==== Funciones de movimiento ====
void forward() {
  analogWrite(ENA, currentSpeed); analogWrite(ENB, currentSpeed);
  digitalWrite(IN1, LOW);  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);  digitalWrite(IN4, HIGH);
}
void backward() {
  analogWrite(ENA, currentSpeed); analogWrite(ENB, currentSpeed);
  digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW);
}
void left() {
  analogWrite(ENA, currentSpeed); analogWrite(ENB, currentSpeed);
  digitalWrite(IN1, LOW);  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW);
}
void right() {
  analogWrite(ENA, currentSpeed); analogWrite(ENB, currentSpeed);
  digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);  digitalWrite(IN4, HIGH);
}
void stopMotors() {
  analogWrite(ENA, 0); analogWrite(ENB, 0);
  digitalWrite(IN1, LOW); digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);
}
