/*
   Codice esplorativo per testare genFSM
   
   https://programmersqtcpp.blogspot.com/2022/03/applicazione-accesso-parcheggio-entry.html
   
   Copyright (C) 2023 Maurilio Pizzurro 

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 1, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <LiquidCrystal.h>
#include <Servo.h>
#include "genFSM.h"  // (1) include genFSM
#include "mtbutton.h"

LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
enum PwrSysState {  
                     IDLE  
                   , AT_POWER_ON 
                   , POWER_OFF
                   , POWER_ON
                   , POWER_SLEEP
                   , AT_POWER_OFF = 255 
                 };
//PwrSysState pwrSysState;     
// (1) Crea istanza in IDLE
GenFSM pwrSysFsm(AT_POWER_ON, AT_POWER_OFF);  

/* Yellow button go to next state*/
const byte PIN_BTN0   = 6;
MtButton btnPower(PIN_BTN0);
/* Green button toggle idle */
const byte PIN_BTN1   = 4;
MtButton btnIdle(PIN_BTN1);

void setup() {
    Serial.begin(115200);
    pinMode(LED_BUILTIN, OUTPUT);
    pinMode(A0, OUTPUT);

    lcd.begin(16, 2);
}


void loop() {
    btnPower.read();
    btnIdle.read();
    pwrSysFsm.run();

    switch (pwrSysFsm.getCurrState()) {
      case AT_POWER_ON:
        if (pwrSysFsm.onEnter()) {
            Serial.println("\nAT_POWER_ON.onEnter");
        } else if (pwrSysFsm.onRun()) {
            
            if (btnIdle.wasPressed()) {
                Serial.println("AT_POWER_ON.onRun");
                Serial.println("change to POWER_SLEEP");
                pwrSysFsm.setState(POWER_SLEEP);
            }
        } else if (pwrSysFsm.onExit()) {
            Serial.println("AT_POWER_ON.onExit");
        }
        break;
      case POWER_ON:
      if (pwrSysFsm.onEnter()) {
            Serial.println("\nPOWER_ON.onEnter");
        } else if (pwrSysFsm.onRun()) {
            
            if (btnIdle.wasPressed()) {
                Serial.println("POWER_ON.onRun");
                Serial.println("change to POWER_SLEEP");
                pwrSysFsm.setState(POWER_SLEEP);
            }
        } else if (pwrSysFsm.onExit()) {
            Serial.println("POWER_ON.onExit");
        }
        break;
      case POWER_OFF:
        if (pwrSysFsm.onEnter()) {
            Serial.println("\nPOWER_OFF.onEnter");
        } else if (pwrSysFsm.onRun()) {
            //Serial.print(".");
            //delay(200);
            if (btnIdle.wasPressed()) {
                Serial.println("POWER_OFF.onRun");
                Serial.println("change to POWER_ON");
                pwrSysFsm.setState(POWER_ON);
            }
        } else if (pwrSysFsm.onExit()) {
            Serial.println("POWER_OFF.onExit");
        }
        break;
      case POWER_SLEEP:
        if (pwrSysFsm.onEnter()) {
            Serial.println("\nPOWER_SLEEP.onEnter");
        } else if (pwrSysFsm.onRun()) {
            
            if (btnIdle.wasPressed()) {
                Serial.println("POWER_SLEEP.onRun");
                Serial.println("change to POWER_OFF");
                pwrSysFsm.setState(POWER_OFF);
            }
        } else if (pwrSysFsm.onExit()) {
            Serial.println("POWER_SLEEP.onExit");
        }
        break;
        
      
      
    }

    /*if (btnNext.wasPressed()) {
        mainState.goNextState();
    } else if (btnIdle.wasPressed()) {
      // toggle idle/active
      if (mainState.isActive())
          mainState.setIdle();
      else {
          mainState.resume();
          Serial.println("resume");
      }
    }
       
    mainState.run();    // (3)
    //switch (mainState.getState()) {
    AMACHINE(mainState.getState()) {
      //case 0: // stato zero di mainState
      ASTATE(0):
        //switch (mainState.subState()) {
        SUB_STATES(mainState.subState()) {  
          //case SS_ENTRY: // sub stato 1 di stato 0
          ASTATE(SS_ENTRY):  
            Serial.println("ENTRY to 0");
          END_STATE(SS_ENTRY);

          //case SS_RUN: // sub stato 2 di stato 0
          ASTATE(SS_RUN): 
            { // blocco di codice per tv
              static uint16_t tv = 0;
              if (mainState.isElapsed(tv)) {
                  tv = 1000;
                  Serial.println("RUN to 0");
                  mainState.setTimer();
              }
            }
            //break;
          END_STATE(SS_RUN); 
          //case SS_EXIT: // sub stato 3 di stato 0
          ASTATE(SS_EXIT):
            Serial.println("EXIT from 0");
            //break;
          END_STATE(SS_EXIT);
        } // end switch (mainState.subState())
        //break;
      END_STATE(0);

      case 1: // stato uno di mainState
        switch (mainState.subState()) {
          case SS_ENTRY: // sub stato 1 di stato 1
            Serial.println("ENTRY to 1");
            break;
          case SS_RUN: // sub stato 2 di stato 1
            {
              static uint16_t tv = 0;
              if (mainState.isElapsed(tv)) {
                  tv = 1000;
                  Serial.println("RUN to 1");
                  mainState.setTimer();
              }
            }
            break;
          case SS_EXIT: // sub stato 3 di stato 1
            Serial.println("EXIT from 1");
          break;
        } // end switch (mainState.subState())
        break;

      case 2: // stato due di mainState
        switch (mainState.subState()) {
          case SS_ENTRY:
            Serial.println("ENTRY to 2");
          break;
          case SS_RUN:
            if (mainState.isElapsed(1000)) {
              Serial.println("RUN to 2");
              mainState.setTimer();
            }
          break;
          case SS_EXIT:
            Serial.println("EXIT from 2");
            mainState.setState(0);
          break;
        }
        break;
      case S_IDLE:
        
        if (mainState.isElapsed(1000)) {
            Serial.println("IDLE");
            mainState.setTimer();
        }
        break;
    }*/
}

nano:12
nano:11
nano:10
nano:9
nano:8
nano:7
nano:6
nano:5
nano:4
nano:3
nano:2
nano:GND.2
nano:RESET.2
nano:0
nano:1
nano:13
nano:3.3V
nano:AREF
nano:A0
nano:A1
nano:A2
nano:A3
nano:A4
nano:A5
nano:A6
nano:A7
nano:5V
nano:RESET
nano:GND.1
nano:VIN
nano:12.2
nano:5V.2
nano:13.2
nano:11.2
nano:RESET.3
nano:GND.3
lcd:VSS
lcd:VDD
lcd:V0
lcd:RS
lcd:RW
lcd:E
lcd:D0
lcd:D1
lcd:D2
lcd:D3
lcd:D4
lcd:D5
lcd:D6
lcd:D7
lcd:A
lcd:K
r1:1
r1:2
servo1:GND
servo1:V+
servo1:PWM
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
led1:A
led1:C
led2:A
led2:C
r2:1
r2:2
r3:1
r3:2