#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>


RF24 radio(10, 9); // CE, CSN						          // NOTE: For other versions of nRF24L01(+) modules, CE and CSN may use different pins (9,10 or 7,8, ...)
													                        // Pins: D9,D10, D11, D12, D13 are typically reserved for nRF24L01+ modules
unsigned long ledTimer = 0;							          // The timer counts from the time the induction cooker is turned on
unsigned long hoodTimer = 0;						          // The timer counts from the time the induction cooker is turned on
unsigned long ledTimer1 = 0;						          // The timer counts from the time the induction cooker turns on the LED (relay)
unsigned long hoodTimer1 = 0;						          // The timer counts from the time the induction cooker turns on the HOOD (relay)
unsigned long LEDmanuallyTurnedOnTimer = 0;			  // The timer counts from the time the LED is manually turned on
unsigned long HOODmanuallyTurnedOnTimer = 0;		  // The timer counts from the time the HOOD is manually turned on
unsigned long HOODturnOnTimer = 0;       			    // The timer counts from the time the induction cooker is turned on to when the HOOD is turned on (with a delay)
bool ledActive = false;				  	       		      // LED state - true when automatically turned on via induction
bool hoodActive = false;			  	       		      // HOOD state - true when automatically turned on via induction
bool LEDmanuallyTurnedOn = false;        			    // LED state - true when manually turned on
bool LEDmanuallyTurnedOffAuto = false;   			    // LED state - true when manually turned off after being turned on via induction
bool HOODmanuallyTurnedOn = false;       			    // HOOD state - true when manually turned on
bool HOODmanuallyTurnedOffAuto = false;  			    // HOOD state - true when manually turned off after being turned on via induction
bool LEDmanuallyTurnedOnDuringInduction = false;  // LED state - true when manually turned on after or during induction
bool HOODmanuallyTurnedOnDuringInduction = false; // HOOD state - true when manually turned on after or during induction

unsigned long HOODTurnOnDelay = 40000;			      // Delay time for turning on the HOOD, default 40s
unsigned long autoTurnOffLEDInduction = 900000;	  // Time to turn off LED after the induction is turned off, default 15 min
unsigned long autoTurnOffHOODInduction = 120000;	// Time to turn off HOOD after the induction is turned off, default 2 min
unsigned long autoTurnOffLEDManual = 3600000;	   	// Time to turn off LED after manual turned on the LED, default 60 min
unsigned long autoTurnOffHOODManual = 3600000;	  // Time to turn off HOOD after manual turned on the HOOD, default 60 min

int inductionState = LOW;					                // Initialize the induction variable to LOW = off
int LEDrelay = 2;                      				    // Digital output controlling the LED relay
int HOODrelay = 3;                     				    // Digital output controlling the HOOD relay
int LEDstatus = 4;                    				    // Digital input monitoring whether the LED is turned on
int HOODstatus = 5;                   				    // Digital input monitoring whether the HOOD is turned on

bool previousLEDStatus = LOW;         	  			  // Previous state of the LED
bool previousHOODStatus = LOW;        	  			  // Previous state of the HOOD
bool currentLEDStatus = LOW;          	  			  // Current state of the LED
bool currentHOODStatus = LOW;         	  			  // Current state of the HOOD



void setup() {
  pinMode(LEDrelay, OUTPUT);     				 	        // Output for turning on the LED relay
  pinMode(HOODrelay, OUTPUT);     					      // Output for turning on the HOOD relay
  pinMode(LEDstatus, INPUT);      					      // Input for checking when the LED is turned on
  pinMode(HOODstatus, INPUT);     					      // Input for checking when the HOOD is turned on
      
  digitalWrite(LEDrelay, HIGH);   					      // Turn off the LED relay at startup (@ LOW level trigger relay)
  digitalWrite(HOODrelay, HIGH);  					      // Turn off the HOOD relay at startup (@ LOW level trigger relay)
 
  //Serial.begin(9600);           					      // Start serial communication - for debugging
    
  radio.begin();
  radio.openReadingPipe(1, 0x1A2B3C4D);   			  // Transmitter/Receiver address, can be arbitrarily set
  radio.setPALevel(RF24_PA_LOW);          			  // Set radio power to LOW (the distance between the induction and the HOOD is typically very small)
  radio.startListening();

  delay(5000);
}



// Function for turning the LED or HOOD relay on and off
void toggleRelay(int pin) {
  digitalWrite(pin, LOW);
  delay(300);										// Short delay to simulate the time it takes to press the button manually; a shorter delay might not be detected by some devices.
  digitalWrite(pin, HIGH);
  delay(300);
}



void loop() {
	
currentLEDStatus = !digitalRead(LEDstatus);   		// Read the LED status - is it on?
currentHOODStatus = !digitalRead(HOODstatus); 		// Read the HOOD status - is it on?

	
 // Check if the LED has turned on
if (currentLEDStatus == HIGH && previousLEDStatus == LOW) { 	// The LED has turned on manually
  if (millis() - ledTimer1 >= 1500) { 				// Check if it's outside the time when the induction was running; default 1500ms
    LEDmanuallyTurnedOnTimer = millis();
    LEDmanuallyTurnedOn = true;
    LEDmanuallyTurnedOffAuto = false;
  } 
  else {											// LED was not manually turned on because it was turned on by the automatic induction
    LEDmanuallyTurnedOn = false;
	  LEDmanuallyTurnedOnTimer = 0;
  }
}

// Check if the LED has turned off
if (currentLEDStatus == LOW && previousLEDStatus == HIGH) { 	// The LED has turned off manually
  LEDmanuallyTurnedOn = false;       				// The LED is currently off
  if (millis() - ledTimer1 >= 1500) { 				// Check if it's outside the time when the induction was running; default 1500ms
  LEDmanuallyTurnedOffAuto = true;
	LEDmanuallyTurnedOnTimer = 0;
	} 
	else 
    LEDmanuallyTurnedOffAuto = false;
}

// Update the previous LED state
previousLEDStatus = currentLEDStatus;

// Check if the HOOD has turned on
if (currentHOODStatus == HIGH && previousHOODStatus == LOW) { 	// The HOOD has turned on manually
  if (millis() - hoodTimer1 >= 1500) { 	// Check if it's outside the time when the induction was running; default 1500ms
    HOODmanuallyTurnedOnTimer = millis();
    HOODmanuallyTurnedOn = true;
    HOODmanuallyTurnedOffAuto = false;
  } else {
    // HOOD was not manually turned on because it was turned on by the automatic induction
    HOODmanuallyTurnedOn = false;
	  HOODmanuallyTurnedOnTimer = 0;
  }
}

// Check if the HOOD has turned off
if (currentHOODStatus == LOW && previousHOODStatus == HIGH) { 	// The HOOD has turned off manually
  HOODmanuallyTurnedOn = false;        	// The HOOD is currently off
  if (millis() - hoodTimer1 >= 1500) { 	// Check if it's outside the time when the induction was running; default 1500ms
    HOODmanuallyTurnedOffAuto = true;
	  HOODmanuallyTurnedOnTimer = 0;
  } 
  else 
    HOODmanuallyTurnedOffAuto = false;
}

// Update the previous HOOD state
previousHOODStatus = currentHOODStatus;


// If the radio is available, check the state of the induction reported by the transmitter
if (radio.available()) {
  radio.read(&inductionState, sizeof(inductionState));
}

if (inductionState == HIGH) { // The induction cooker has turned on
  ledTimer = millis();
  hoodTimer = millis();

  if (!ledActive && !LEDmanuallyTurnedOn && !LEDmanuallyTurnedOffAuto) { // Turn on the LED when this condition is met
    toggleRelay(LEDrelay);  // Turn on the LED relay - for 0.3s
    ledActive = true;
    ledTimer1 = millis();
  }

  if (!hoodActive && !HOODmanuallyTurnedOn && !HOODmanuallyTurnedOffAuto) { // Start the HOOD turn-on delay procedure when this condition is met
    hoodActive = true;
    HOODturnOnTimer = millis();
  }

    if (LEDmanuallyTurnedOn) 	// Check if the LED was manually turned on after or during the induction
	 LEDmanuallyTurnedOnDuringInduction = true;
	else 
     LEDmanuallyTurnedOnDuringInduction = false;
  

	if (HOODmanuallyTurnedOn) 	// Check if the HOOD was manually turned on after or during the induction
     HOODmanuallyTurnedOnDuringInduction = true;
	else 
     HOODmanuallyTurnedOnDuringInduction = false;
  
}

if (hoodActive && inductionState && !HOODmanuallyTurnedOn && !HOODmanuallyTurnedOffAuto && HOODturnOnTimer > 0 && millis() - HOODturnOnTimer >= HOODTurnOnDelay) {   // Turn on HOOD with a delay
  toggleRelay(HOODrelay); // Turn on the HOOD relay - for 0.3s
  hoodTimer1 = millis();
  HOODturnOnTimer = 0; 	// Reset
} 
else if (HOODturnOnTimer > 0 && millis() - HOODturnOnTimer >= HOODTurnOnDelay) {
  hoodActive = false;
  HOODturnOnTimer = 0; 	// Reset
}

// Monitoring variable states for debugging:
/* 
Serial.print("inductionState: ");
Serial.println(inductionState);
Serial.print("ledActive: ");
Serial.println(ledActive);
Serial.print("hoodActive: ");
Serial.println(hoodActive);
Serial.print("currentLEDStatus: ");
Serial.println(currentLEDStatus);
Serial.print("LEDmanuallyTurnedOn: ");
Serial.println(LEDmanuallyTurnedOn);
Serial.print("LEDmanuallyTurnedOffAuto: ");
Serial.println(LEDmanuallyTurnedOffAuto);
Serial.print("currentHOODStatus: ");
Serial.println(currentHOODStatus);
Serial.print("HOODmanuallyTurnedOn: ");
Serial.println(HOODmanuallyTurnedOn);
Serial.print("HOODmanuallyTurnedOffAuto: ");
Serial.println(HOODmanuallyTurnedOffAuto);

Serial.print("ledTimer: ");
Serial.println(ledTimer);
Serial.print("ledTimer1: ");
Serial.println(ledTimer1);
Serial.print("hoodTimer: ");
Serial.println(hoodTimer);
Serial.print("hoodTimer1: ");
Serial.println(hoodTimer1);
Serial.print("LEDmanuallyTurnedOnTimer: ");
Serial.println(LEDmanuallyTurnedOnTimer);
Serial.print("HOODmanuallyTurnedOnTimer: ");
Serial.println(HOODmanuallyTurnedOnTimer);
Serial.print("HOODturnOnTimer: ");
Serial.println(HOODturnOnTimer);
*/

  
if ((ledActive || LEDmanuallyTurnedOnDuringInduction) && !inductionState && !LEDmanuallyTurnedOffAuto && millis() - ledTimer >= autoTurnOffLEDInduction) { // Turn off the LED after the induction turns off
  toggleRelay(LEDrelay);  // Turn off the LED relay - for 0.3s
  ledActive = false;
  LEDmanuallyTurnedOnDuringInduction = false;
  LEDmanuallyTurnedOn = false;
}

if ((hoodActive || HOODmanuallyTurnedOnDuringInduction) && !inductionState && !HOODmanuallyTurnedOffAuto && millis() - hoodTimer >= autoTurnOffHOODInduction) { // Turn off the HOOD after the induction turns off
  toggleRelay(HOODrelay); // Turn off the HOOD relay - for 0.3s
  hoodActive = false;
  HOODmanuallyTurnedOnDuringInduction = false;
  HOODmanuallyTurnedOn = false;
}

if (LEDmanuallyTurnedOffAuto && millis() - ledTimer1 >= 2000) { // If more than 2s have passed since the last induction-based LED activation and the LED was manually turned off
  ledActive = false;
  if (!inductionState)
    LEDmanuallyTurnedOffAuto = false;
}

if (HOODmanuallyTurnedOffAuto && millis() - hoodTimer1 >= 2000) { // If more than 2s have passed since the last induction-based HOOD activation and the HOOD was manually turned off
  hoodActive = false;
  if (!inductionState)
    HOODmanuallyTurnedOffAuto = false;
}

if (!inductionState && LEDmanuallyTurnedOn && millis() - LEDmanuallyTurnedOnTimer >= autoTurnOffLEDManual) { // If more than X minutes have passed since the last manual LED activation, turn off the LED
  toggleRelay(LEDrelay);	// Turn off the LED relay - for 0.3s
  LEDmanuallyTurnedOn = false;
  ledActive = false;
  ledTimer = 0;
}

if (!inductionState && HOODmanuallyTurnedOn && millis() - HOODmanuallyTurnedOnTimer >= autoTurnOffHOODManual) { // If more than X minutes have passed since the last manual HOOD activation, turn off the HOOD
  toggleRelay(HOODrelay);	// Turn off the HOOD relay - for 0.3s
  HOODmanuallyTurnedOn = false;
  hoodActive = false;
  hoodTimer = 0;
}

delay(10);

}