// dak.cpp - het kasdak als toestandsmachine (hoofdstuk 32; motor en eindeloop: hoofdstuk 26)
#include <Arduino.h>
#include "pinnen.h"
#include "dak.h"

void melding(const char* tekst);                  // staat in de schets zelf (met de tijd van de klok)

const unsigned long TIMEOUT_MS = 12000;           // langer dan 12 s bewegen: er klopt iets niet
const int PWM_DAK = 232;                          // 0,10 m/s bij 12,8 V (hoofdstuk 26)
const char* DAK_NAAM[] = {"DICHT", "OPENEN", "OPEN", "SLUITEN", "GESTOPT", "DAK_FOUT"};

DakToestand dak = DICHT;
unsigned long dakSinds = 0;
bool wensOpen = false, geblokkeerd = false;

const char* dakNaam(DakToestand t) { return DAK_NAAM[t]; }

void motor(int richting) {                        // +1 sluiten, -1 openen, 0 stil: nooit beide tegelijk
  analogWrite(PWM_DICHT, richting > 0 ? PWM_DAK : 0);
  analogWrite(PWM_OPEN, richting < 0 ? PWM_DAK : 0);
}

void dakNaar(DakToestand nieuw, unsigned long nu) {
  dak = nieuw;
  dakSinds = nu;
  if (nieuw == OPENEN) motor(-1);                 // bij binnenkomen: de motor
  else if (nieuw == SLUITEN) motor(+1);
  else motor(0);
  char tekst[24] = "dak: ";
  strcat(tekst, DAK_NAAM[nieuw]);
  melding(tekst);
}

void dakStart(unsigned long nu) {
  if (digitalRead(EIND_DICHT) == HIGH) dakNaar(DICHT, nu);
  else if (digitalRead(EIND_OPEN) == HIGH) { wensOpen = true; dakNaar(OPEN, nu); }
  else dakNaar(SLUITEN, nu);                      // onbekende stand: veilig dichtdoen
}

void dakVraag(bool open) { wensOpen = open; }

void dakKnop(unsigned long nu) {
  if (geblokkeerd) return;
  switch (dak) {
    case DICHT:   wensOpen = true; break;
    case OPEN:    wensOpen = false; break;
    case OPENEN:
    case SLUITEN: dakNaar(GESTOPT, nu); break;    // een druk tijdens de beweging = stoppen
    case GESTOPT: wensOpen = false; dakNaar(SLUITEN, nu); break;
    case DAK_FOUT: break;                         // alleen dakHerstel() haalt het dak hieruit
  }
}

void dakHerstel(unsigned long nu) {
  if (dak == DAK_FOUT) {
    wensOpen = false;
    dakNaar(SLUITEN, nu);
  }
}

void dakBlokkeer(bool aan, unsigned long nu) {
  geblokkeerd = aan;
  if (aan && (dak == OPENEN || dak == SLUITEN)) dakNaar(GESTOPT, nu);
}

void taakDak(unsigned long nu) {
  unsigned long t = nu - dakSinds;
  switch (dak) {
    case DICHT:
      if (wensOpen && !geblokkeerd) dakNaar(OPENEN, nu);
      break;
    case OPEN:
      if (!wensOpen && !geblokkeerd) dakNaar(SLUITEN, nu);
      break;
    case OPENEN:
      if (digitalRead(EIND_OPEN) == HIGH) dakNaar(OPEN, nu);
      else if (t > TIMEOUT_MS) dakNaar(DAK_FOUT, nu);
      break;
    case SLUITEN:
      if (digitalRead(EIND_DICHT) == HIGH) dakNaar(DICHT, nu);
      else if (t > TIMEOUT_MS) dakNaar(DAK_FOUT, nu);
      break;
    case GESTOPT:                                 // wacht op een knopdruk
    case DAK_FOUT:                                // wacht op dakHerstel()
      break;
  }
}
