#include "U8glib.h"
#include <IRremote.hpp>
#include <string.h>
#include <Arduino.h>
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST);

const int select = 5;
const int confirm = 6;
const int errorLed = A1;
const int comfirmationLed = A0;
bool askingMode = true;
bool transMode = false;
bool receiveMode = false;
bool receivedHex = false;
bool mainMenuDelay = false;
int selectedChannel = 1;
int prev = HIGH;
uint32_t data[10];
uint32_t rawData[10]; 
uint32_t protocol[10];
uint32_t address[10];
uint32_t command[10];
int_fast8_t repeats = 1;
int rawLen[10];

void setup() {
  Serial.begin(19200);
  u8g.setFont(u8g_font_tpssb);
  u8g.setColorIndex(1);
  pinMode(select, INPUT);
  pinMode(confirm, INPUT);
  pinMode(errorLed, OUTPUT);
  pinMode(comfirmationLed, OUTPUT);
  digitalWrite(errorLed, LOW);
  digitalWrite(comfirmationLed, LOW);
  IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK);
  IrSender.begin(IR_SEND_PIN, DISABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN);
}

void loop() {
  u8g.firstPage();
  if(askingMode){
    if(digitalRead(select) == prev){
      receiveMode = true;
      transMode = false;
      displayModeSelect(1);
      prev = HIGH;
    }
    else{
      transMode = true;
      receiveMode = false;
      displayModeSelect(0);
      prev = LOW;
    }
    if(mainMenuDelay){
      delay(400);
    }
  }
  if(digitalRead(confirm) == LOW || !askingMode){
    if (transMode){
      displayTransmittingMode(selectedChannel);
      if (digitalRead(select) == LOW){
        selectedChannel++;
        if (selectedChannel > 10){
        selectedChannel = 1;
        }
      }
      delay(200);
      if (digitalRead(confirm) == LOW && !askingMode){
        displayStoring();
        transmit(selectedChannel);
      }
    }
    else if(receiveMode){
      if (digitalRead(select) == LOW){
        selectedChannel++;
        if (selectedChannel > 10){
        selectedChannel = 1;
        }
      }
      delay(200);
      if (digitalRead(confirm) == LOW && !askingMode){
        displayStoring();
        receive(selectedChannel);
      }
      else{
        displayReceivingMode(selectedChannel);
      }
    }
    askingMode = false;
  }
  if(!digitalRead(select) && !digitalRead(confirm)){
    askingMode = true;
    transMode = false;
    receiveMode = false;
    receivedHex = false;
    mainMenuDelay = true;
    selectedChannel = 1;
  }
  delay(200);
}

void displayModeSelect(int Offset){
  do{
    u8g.drawStr(22, 15, "Receive");
    u8g.drawFrame(10, 0, 68, 25);
    u8g.drawStr(19, 50, "Transmit");
    u8g.drawFrame(10, 35, 68, 25);
    u8g.drawStr(80, (50 - (Offset*33)), "<--");
  } while (u8g.nextPage());
}

void displayReceivingMode(int channel){
  char channelString[2];
  sprintf(channelString, "%d", channel);
  do{
    u8g.drawStr(38, 15, "Receiving");
    u8g.drawFrame(27, 0, 75, 25);
    u8g.drawStr(33, 45, "Channel:");
    u8g.drawStr(85, 45, channelString);
  } while (u8g.nextPage());  
}

void displayStoring(){
  do{
    u8g.drawStr(42, 35, "Storing");
  } while (u8g.nextPage());  
}

void displayTransmittingMode(int channel){
  char channelString[2];
  sprintf(channelString, "%d", channel);
  do{
    u8g.drawStr(23, 15, "Transmitting");
    u8g.drawFrame(17, 0, 90, 25);
    u8g.drawStr(33, 45, "Channel:");
    u8g.drawStr(85, 45, channelString);
  } while (u8g.nextPage());
}

void receive(int selectedChannel) {
  receivedHex = false;
  do {
    if (IrReceiver.decode()) {
      data[selectedChannel] = IrReceiver.decodedIRData.decodedRawData, HEX;
      if (String(data[selectedChannel]) != "ffffffff" && String(IrReceiver.decodedIRData.decodedRawData, HEX).length() == 8){
        rawData[selectedChannel] = IrReceiver.decodedIRData.decodedRawData;
        rawLen[selectedChannel] = sizeof(rawData[selectedChannel]);
        receivedHex = true;
      }
    }
    if (receivedHex){
      Serial.print("Stored \"");
      Serial.print(rawData[selectedChannel]);
      ledSuccesfull(true);
    }
    else {
      receivedHex = true;
      Serial.print(data[selectedChannel]);
      ledSuccesfull(false);
    }
    IrReceiver.resume();
  } while (!receivedHex);
}

void transmit(int channel) {
  uint8_t pulseWidths[100];
  bool succes = false;
  pulseWidths[0] = (rawData[selectedChannel] >> 8) & 0xFF; // High byte
  pulseWidths[1] = rawData[selectedChannel] & 0xFF;      // Low byte
  IrSender.sendRaw(pulseWidths, 2, 38);
  Serial.println("IR code sent successfully");
  IrReceiver.resume();
  if(rawData[selectedChannel] != 0){
    succes = true;
  }
  ledSuccesfull(succes);
}

void ledSuccesfull(bool succes){
  if (succes){
    digitalWrite(comfirmationLed, HIGH);
    delay(300);
    digitalWrite(comfirmationLed, LOW);
  }
  else{
    digitalWrite(errorLed, HIGH);
    delay(300);
    digitalWrite(errorLed, LOW);
  }
}
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
led1:A
led1:C
led2:A
led2:C
ir1:GND
ir1:VCC
ir1:DAT
oled1:GND
oled1:VCC
oled1:SCL
oled1:SDA
led3:A
led3:C
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
r1:1
r1:2
r2:1
r2:2
sw1:1
sw1:2
sw1:3