/*
 * =============================================
 *   SCAREDY CAT — Ultrasonic + LCD Only
 * =============================================
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define TRIG_PIN 9
#define ECHO_PIN 8

#define DIST_PANIC   100
#define DIST_SCARED  40

#define MODE_CONFIRM_MS 1000

LiquidCrystal_I2C MyLCD(0x27, 20, 4);

uint8_t fullPixel[] = {0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f};

// ── State ─────────────────────────────────────
enum CatState { HAPPY, PANIC, SCARED };
CatState confirmedState  = HAPPY;
CatState candidateState  = HAPPY;
CatState lastDrawnState  = SCARED;

unsigned long candidateStartTime = 0;

// ── Panic animation timing ────────────────────
unsigned long lastPanicFrameTime = 0;
int panicFrame = 0;

// ─────────────────────────────────────────────
//  Distance
// ─────────────────────────────────────────────
long getDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  long duration = pulseIn(ECHO_PIN, HIGH, 30000);
  if (duration == 0) return 999;
  return duration * 0.034 / 2;
}

CatState getStateForDistance(long dist) {
  if (dist < DIST_SCARED) return SCARED;
  if (dist < DIST_PANIC)  return PANIC;
  return HAPPY;
}

// ─────────────────────────────────────────────
//  LCD Faces
// ─────────────────────────────────────────────

void drawHappy() {
  MyLCD.clear();
  MyLCD.setCursor(4, 1);  MyLCD.write(byte(0));
  MyLCD.setCursor(15, 1); MyLCD.write(byte(0));
  MyLCD.setCursor(3, 2);  MyLCD.write(byte(0));
  MyLCD.setCursor(5, 2);  MyLCD.write(byte(0));
  MyLCD.setCursor(14, 2); MyLCD.write(byte(0));
  MyLCD.setCursor(16, 2); MyLCD.write(byte(0));
  MyLCD.setCursor(2, 3);  MyLCD.write(byte(0));
  MyLCD.setCursor(6, 3);  MyLCD.write(byte(0));
  MyLCD.setCursor(13, 3); MyLCD.write(byte(0));
  MyLCD.setCursor(17, 3); MyLCD.write(byte(0));
}

void drawPanicFrame(int frame) {
  MyLCD.clear();

  if (frame == 0) {
    MyLCD.setCursor(1,1); MyLCD.write(byte(0));
    MyLCD.setCursor(2,1); MyLCD.write(byte(0));
    MyLCD.setCursor(12,1);MyLCD.write(byte(0));
    MyLCD.setCursor(13,1);MyLCD.write(byte(0));
  }
  else if (frame == 1) {
    MyLCD.setCursor(3,1); MyLCD.write(byte(0));
    MyLCD.setCursor(4,1); MyLCD.write(byte(0));
    MyLCD.setCursor(14,1);MyLCD.write(byte(0));
    MyLCD.setCursor(15,1);MyLCD.write(byte(0));
  }
  else {
    MyLCD.setCursor(6,1); MyLCD.write(byte(0));
    MyLCD.setCursor(7,1); MyLCD.write(byte(0));
    MyLCD.setCursor(17,1);MyLCD.write(byte(0));
    MyLCD.setCursor(18,1);MyLCD.write(byte(0));
  }
}

void drawScared() {
  MyLCD.clear();
  MyLCD.setCursor(2,1);  MyLCD.write(byte(0));
  MyLCD.setCursor(3,1);  MyLCD.write(byte(0));
  MyLCD.setCursor(14,1); MyLCD.write(byte(0));
  MyLCD.setCursor(15,1); MyLCD.write(byte(0));
}

// ─────────────────────────────────────────────
//  Setup
// ─────────────────────────────────────────────
void setup() {
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);

  MyLCD.init();
  MyLCD.backlight();
  MyLCD.createChar(0, fullPixel);
  MyLCD.clear();

  Serial.begin(9600);
}

// ─────────────────────────────────────────────
//  Loop
// ─────────────────────────────────────────────
void loop() {
  unsigned long now = millis();

  long dist        = getDistance();
  CatState reading = getStateForDistance(dist);

  if (reading != candidateState) {
    candidateState     = reading;
    candidateStartTime = now;
  }

  if (candidateState != confirmedState) {
    if (now - candidateStartTime >= MODE_CONFIRM_MS) {
      confirmedState = candidateState;
      panicFrame     = 0;

      if (confirmedState == HAPPY)  drawHappy();
      if (confirmedState == PANIC)  drawPanicFrame(0);
      if (confirmedState == SCARED) drawScared();
      lastPanicFrameTime = now;
    }
  }

  if (confirmedState == PANIC && now - lastPanicFrameTime >= 1000) {
    panicFrame = (panicFrame + 1) % 3;
    drawPanicFrame(panicFrame);
    lastPanicFrameTime = now;
  }

  delay(100);
}