#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <Arduino.h>
#include <IRremote.h>

RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

#define PIN_RECEIVER 9   // Signal Pin of IR receiver
IRrecv receiver(PIN_RECEIVER);

// set the LCD address to 0x27 and for a 20 chars and 4 line display
LiquidCrystal_I2C lcd(0x27, 20, 4);

const int relay1Pin = 6;
const int relay1PinPIR = 11;  //same relay as relay1Pin but controlled separate
const int relay2Pin = 7;
const int relay3Pin = 8;
const int button1Pin = 3;
const int button2Pin = 4;
const int button3Pin = 5;
const int button4Pin = 10;
const int OnHour = 12;
const int OnMinute = 48;
const int OffHour = 22;
const int OffMinute = 00;

const unsigned long currentTime = 0;

int lastState1 = HIGH;
int lastState2 = HIGH;
int lastState3 = HIGH;
int lastState4 = HIGH;


int inputPin = 2;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status

void setup() {
  Serial.begin(115200);
  pinMode( relay1Pin, OUTPUT);
  pinMode( relay1PinPIR, OUTPUT);
  pinMode( relay2Pin, OUTPUT);
  pinMode( relay3Pin, OUTPUT);

  pinMode( button1Pin, INPUT);
  pinMode( button2Pin, INPUT);
  pinMode( button3Pin, INPUT);
  pinMode( button4Pin, INPUT);
  
  digitalWrite( relay1Pin, LOW);
  digitalWrite( relay1PinPIR, LOW);
  digitalWrite( relay2Pin, LOW);
  digitalWrite( relay3Pin, LOW);

  lcd.init();       // initialize the lcd
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(1, 0);
  lcd.print("A 240V controller");
  lcd.setCursor(0, 1);
  lcd.print("with remote & timer");
  lcd.setCursor(0, 2);
  lcd.print("   Created by Rod");
  lcd.setCursor(0, 3);
  lcd.print("Power to the oldies!");
  delay(1500);
  lcd.setCursor(0, 0);
  lcd.print("                    ");
  lcd.setCursor(0, 1);
  lcd.print("                    ");
  lcd.setCursor(0, 2);
  lcd.print("                    ");
  lcd.setCursor(0, 3);
  lcd.print("                    ");
  // lcd.setCursor(0,2);
  //lcd.print("Arduino LCM IIC 2004");
  // lcd.setCursor(2,3);
  //lcd.print("Power By Ec-yuan!");
  delay(1500);

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    abort();
  }

  //lcd.begin(0, 3);
  //lcd.print("<press a button>");
  receiver.enableIRIn(); // Start the receiver
}

void loop()
{
  timeDisplay(); //calls function to print the date/time on LCD
  
  // Checks received an IR signal
  if (receiver.decode()) {
    translateIR();
    receiver.resume();  // Receive the next value
  }
  
  DateTime t = rtc.now();
  //Serial.print(t.hour());
  //Serial.print(" hour(s), ");
  //Serial.print(t.minute());
  //Serial.print(" minute(s)");
  //Serial.println(" ");
  //delay (1000);
  
  if(t.hour() == OnHour && t.minute() == OnMinute){
    digitalWrite(relay1Pin,HIGH);
      lcd.print("Relay 1 is ON      ");
//    Serial.println("LIGHT ON");
    }
    
    else if(t.hour() == OffHour && t.minute() == OffMinute){
      lcd.print("Relay 1 is OFF     ");
      digitalWrite(relay1Pin,LOW);
//      Serial.println("LIGHT OFF");
    } 
 val = digitalRead(inputPin);  // read input value
  if (val == HIGH) {            // check if the input is HIGH
    digitalWrite(relay1PinPIR, HIGH);  // turn LED ON
    if (pirState == LOW) {
      // we have just turned on
      lcd.setCursor(0, 2);
      lcd.print("Relay 1 is ON      ");
      unsigned long currentTime = millis();
      //Serial.print("Motion detected at : ");
      //Serial.println(currentTime);
      // We only want to print on the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(relay1PinPIR, LOW); // turn LED OFF
    if (pirState == HIGH && digitalRead((button1Pin)) == LOW){
      // we have just turned of
      lcd.setCursor(0, 2);
      lcd.print("Relay 1 is OFF      ");
      unsigned long currentTime = millis();
  //    Serial.print("Motion ended at : ");
  //    Serial.println(currentTime);
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }
  
int value1 = digitalRead((button1Pin));
//Serial.print(value1);
//Serial.print(" , ");
//Serial.println(pirState);
if (lastState1 != value1) {
  lastState1 = value1;
  if (value1 == HIGH) {
    digitalWrite( relay1Pin, HIGH);
    lcd.setCursor(0, 2);
    lcd.print("Relay 1 is ON      ");
  }
  if (value1 == LOW) {
    digitalWrite( relay1Pin, LOW);
    lcd.setCursor(0, 2);
    lcd.print("Relay 1 is OFF     ");
  }
}

int value2 = digitalRead((button2Pin));
//Serial.println(value1);
if (lastState2 != value2) {
  lastState2 = value2;
  if (value2 == HIGH) {
    digitalWrite( relay2Pin, HIGH);
    lcd.setCursor(0, 2);
    lcd.print("Relay 2 is ON      ");
  }
  if (value2 == LOW) {
    digitalWrite( relay2Pin, LOW);
    lcd.setCursor(0, 2);
    lcd.print("Relay 2 is OFF      ");
  }
}

int value3 = digitalRead((button3Pin));
//Serial.println(value3);
if (lastState3 != value3) {
  lastState3 = value3;
  if (value3 == HIGH) {
    digitalWrite( relay3Pin, HIGH);
    lcd.setCursor(0, 2);
    lcd.print("Relay 3 is ON      ");
  }
  if (value3 == LOW) {
    digitalWrite( relay3Pin, LOW);
    lcd.setCursor(0, 2);
    lcd.print("Relay 3 is OFF     ");
  }
}

int value4 = digitalRead(button4Pin);
//Serial.print(value4);
//Serial.print(" , ");
//Serial.println(lastState4);
if (lastState4 != value4) {
  lastState4 = value4;
  if (value4 == HIGH) {
    digitalWrite( relay1Pin, HIGH);
    digitalWrite( relay2Pin, HIGH);
    digitalWrite( relay3Pin, HIGH);
    lcd.setCursor(0, 2);
    lcd.print("All relays are ON      ");
  }
  if (value4 == LOW) {
    digitalWrite( relay1Pin, LOW);
    digitalWrite( relay2Pin, LOW);
    digitalWrite( relay3Pin, LOW);
    lcd.setCursor(0, 2);
    lcd.print("All relays are OFF     ");
  }
}
}

void lcdPrint(char* text)
{
  //lcd.clear();
  //lcd.setCursor(0, 2);
  //lcd.print("button pressed:");
  lcd.setCursor(0, 3);
  lcd.print(text);
  lcd.print(" code: ");
  lcd.print(receiver.decodedIRData.command);
}

void translateIR()
{
  // Takes command based on IR code received
  switch (receiver.decodedIRData.command) {
    case 162:
      lcdPrint("POWER");
      break;
    case 226:
      lcdPrint("MENU");
      break;
    case 34:
      lcdPrint("TEST");
      break;
    case 2:
      lcdPrint("PLUS");
      break;
    case 194:
      lcdPrint("BACK");
      break;
    case 224:
      lcdPrint("PREV.");
      break;
    case 168:
      lcdPrint("PLAY");
      break;
    case 144:
      lcdPrint("NEXT");
      break;
    case 104:
      lcdPrint("num: 0");
      break;
    case 152:
      lcdPrint("MINUS");
      break;
    case 176:
      lcdPrint("key: C");
      break;
    case 48:
      lcdPrint("num: 1");
      break;
    case 24:
      lcdPrint("num: 2");
      break;
    case 122:
      lcdPrint("num: 3");
      break;
    case 16:
      lcdPrint("num: 4");
      break;
    case 56:
      lcdPrint("num: 5");
      break;
    case 90:
      lcdPrint("num: 6");
      break;
    case 66:
      lcdPrint("num: 7");
      break;
    case 74:
      lcdPrint("num: 8");
      break;
    case 82:
      lcdPrint("num: 9");
      break;
    default:
      //lcd.clear();
      lcd.setCursor(0, 3);
      lcd.print(receiver.decodedIRData.command);
      lcd.print(" other button");
  }
}

void timeDisplay()
{
  DateTime now = rtc.now();
  lcd.setCursor(0, 0);
  lcd.print("Time: ");
  lcd.setCursor(10, 0);
  lcd.print(now.year(), DEC);
  lcd.setCursor(14, 0);
  lcd.print('/');
  lcd.setCursor(15, 0);
  lcd.print(now.month(), DEC);
  lcd.setCursor(17, 0);
  lcd.print('/');
  lcd.setCursor(18, 0);
  lcd.print(now.day(), DEC);

  lcd.setCursor(0, 1);
  lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
  lcd.setCursor(10, 1);
  lcd.print(now.hour(), DEC);
  lcd.setCursor(12, 1);
  lcd.print(':');
  lcd.setCursor(14, 1);
  lcd.print(now.minute(), DEC);
  lcd.setCursor(16, 1);
  lcd.print(':');
  lcd.setCursor(18, 1);
  lcd.print(now.second(), DEC);
  //  delay(3000);
  }
GND5VSDASCLSQWRTCDS1307+