#include "Shield_RichShield2.h"

// FastLED verlangt den Pin zwingend als Präprozessor-Makro für das Template
#define PIN_RGB A3 

Shield_RichShield2::Shield_RichShield2() : 
  btnEncoder(4), // SW Pin
  _oneWire(5),   // DS18B20 Pin
  _sensors(&_oneWire),
  _batteryDisplay(10, 11), // CLK, DIO
  _encoderPos(0),
  _lastEncCLK(HIGH)
{
}

void Shield_RichShield2::begin() {
  // Encoder Pins
  pinMode(_pinEncCLK, INPUT);
  pinMode(_pinEncDT, INPUT);
  btnEncoder.begin();

  // Ultraschall & PIR
  pinMode(_pinUsTrig, OUTPUT);
  pinMode(_pinUsEcho, INPUT);
  pinMode(_pinPIR, INPUT);

  // DS18B20
  _sensors.begin();

  // Batterie Anzeige
  _batteryDisplay.init();
  _batteryDisplay.set(2); 
  _batteryDisplay.displayLevel(0);

  // 16x8 Matrix
  _matrix.begin(0x70);
  _matrix.setRotation(1);
  _matrix.setTextWrap(false);
  _matrix.setTextColor(LED_ON);
  _matrix.clear();
  _matrix.writeDisplay();

  // RGB LEDs (WS2812)
  FastLED.addLeds<WS2812, PIN_RGB, GRB>(_leds, 4);
  FastLED.setBrightness(50);
  clearRGB();
  
  // Initiale Encoder-Messung
  _lastEncCLK = digitalRead(_pinEncCLK);
}

void Shield_RichShield2::update() {
  btnEncoder.update();

  // Sehr schlankes Polling für den Encoder
  int currentCLK = digitalRead(_pinEncCLK);
  if (currentCLK != _lastEncCLK && currentCLK == HIGH) {
    if (digitalRead(_pinEncDT) != currentCLK) {
      _encoderPos++;
    } else {
      _encoderPos--;
    }
  }
  _lastEncCLK = currentCLK;
}

// --- Encoder ---
int Shield_RichShield2::getEncoderPosition() { return _encoderPos; }
void Shield_RichShield2::resetEncoder() { _encoderPos = 0; }

// --- Sensoren ---
float Shield_RichShield2::getTemperature() {
  _sensors.requestTemperatures(); 
  return _sensors.getTempCByIndex(0);
}

long Shield_RichShield2::getDistance() {
  digitalWrite(_pinUsTrig, LOW);
  delayMicroseconds(2);
  digitalWrite(_pinUsTrig, HIGH);
  delayMicroseconds(10);
  digitalWrite(_pinUsTrig, LOW);
  long duration = pulseIn(_pinUsEcho, HIGH, 30000); 
  if (duration == 0) return 999; // Nichts gefunden / Out of Range
  return (duration / 2) / 29.1;
}

bool Shield_RichShield2::isMotionDetected() {
  return digitalRead(_pinPIR) == HIGH;
}

int Shield_RichShield2::getMicLevel() {
  return analogRead(_pinMic);
}

int Shield_RichShield2::getMicPercent() {
  int raw = analogRead(_pinMic);
  int percent = map(raw, 0, 1023, 0, 100);
  return constrain(percent, 0, 100);
}

// --- Joystick ---
int Shield_RichShield2::getJoyX() { return analogRead(_pinJoyX); }
int Shield_RichShield2::getJoyY() { return analogRead(_pinJoyY); }

String Shield_RichShield2::getJoyDirection() {
  int x = analogRead(_pinJoyX);
  int y = analogRead(_pinJoyY);
  if (x < 200) return "LINKS";
  if (x > 800) return "RECHTS";
  if (y < 200) return "UNTEN";
  if (y > 800) return "OBEN";
  return "MITTE";
}

// --- Ausgaben ---
void Shield_RichShield2::setBatteryLevel(uint8_t level) {
  if(level > 7) level = 7;
  _batteryDisplay.displayLevel(level);
}

void Shield_RichShield2::setBatteryPercent(uint8_t percent) {
  uint8_t level = map(percent, 0, 100, 0, 7);
  _batteryDisplay.displayLevel(level);
}

void Shield_RichShield2::setRGB(uint8_t index, uint8_t r, uint8_t g, uint8_t b) {
  if(index < 4) {
    _leds[index] = CRGB(r, g, b);
    FastLED.show();
  }
}

void Shield_RichShield2::clearRGB() {
  FastLED.clear();
  FastLED.show();
}

// --- Matrix ---
void Shield_RichShield2::showMatrixText(String text) {
  _matrix.clear();
  _matrix.setCursor(0, 0);
  _matrix.print(text);
  _matrix.writeDisplay();
}

void Shield_RichShield2::showMatrixNumber(int num) {
  _matrix.clear();
  _matrix.setCursor(2, 1);
  _matrix.print(num);
  _matrix.writeDisplay();
}

void Shield_RichShield2::setMatrixPixel(int x, int y, bool state) {
  _matrix.drawPixel(x, y, state ? LED_ON : LED_OFF);
  _matrix.writeDisplay();
}

void Shield_RichShield2::clearMatrix() {
  _matrix.clear();
  _matrix.writeDisplay();
}