#include <IRremote.hpp>
enum class Control : uint32_t {
  Forward = 0xEE111000,
  Backward = 0xEA151000,
  Left = 0xED121000,
  Right = 0xEB141000,
  Off = 0xEC131000
};
enum class Direction {
  Forward,
  Backward,
  Off
};
const int ir_receive_pin = 5;
const int motor_1_direction_pin_1 = 8;
const int motor_1_direction_pin_2 = 9;
const int motor_1_speed_pin = 12;
const int motor_2_direction_pin_1 = 10;
const int motor_2_direction_pin_2 = 11;
const int motor_2_speed_pin = 13;
void setup()
{
  Serial.begin(9600);
  Serial.println("Starting...");
  IrReceiver.begin(ir_receive_pin, ENABLE_LED_FEEDBACK); // Start the receiver
  setup_motor(motor_1_direction_pin_1, motor_1_direction_pin_2, motor_1_speed_pin);
  setup_motor(motor_2_direction_pin_1, motor_2_direction_pin_2, motor_2_speed_pin);
}
void setup_motor(int direction_pin_1, int direction_pin_2, int speed_pin) {
  pinMode(direction_pin_1, OUTPUT);
  pinMode(direction_pin_2, OUTPUT);
  pinMode(speed_pin, OUTPUT);
}
void change_motor_direction(Direction direction, int direction_pin_1, int direction_pin_2) {
  switch (direction) {
    case Direction::Forward: {
        digitalWrite(direction_pin_1, HIGH);
        digitalWrite(direction_pin_2, LOW);
        break;
      }
    case Direction::Backward: {
        digitalWrite(direction_pin_1, LOW);
        digitalWrite(direction_pin_2, HIGH);
        break;
      }
    case Direction::Off: {
        digitalWrite(direction_pin_1, LOW);
        digitalWrite(direction_pin_2, LOW);
        break;
      }
  }
}
void forward() {
  Direction direction = Direction::Forward;
  change_motor_direction(direction, motor_1_direction_pin_1, motor_1_direction_pin_2);
  change_motor_direction(direction, motor_2_direction_pin_1, motor_2_direction_pin_2);
}
void backward() {
  Direction direction = Direction::Backward;
  change_motor_direction(direction, motor_1_direction_pin_1, motor_1_direction_pin_2);
  change_motor_direction(direction, motor_2_direction_pin_1, motor_2_direction_pin_2);
}
void left() {
  change_motor_direction(Direction::Off, motor_1_direction_pin_1, motor_1_direction_pin_2);
  change_motor_direction(Direction::Forward, motor_2_direction_pin_1, motor_2_direction_pin_2);
}
void right() {
  change_motor_direction(Direction::Off, motor_1_direction_pin_1, motor_1_direction_pin_2);
  change_motor_direction(Direction::Forward, motor_2_direction_pin_1, motor_2_direction_pin_2);
}
void off() {
  Direction direction = Direction::Off;
  change_motor_direction(direction, motor_1_direction_pin_1, motor_1_direction_pin_2);
  change_motor_direction(direction, motor_2_direction_pin_1, motor_2_direction_pin_2);
}
void loop() {
  if (IrReceiver.decode()) {
    uint32_t control = IrReceiver.decodedIRData.decodedRawData;
    switch ((Control)control) {
      case Control::Forward: {
          forward();
          Serial.println("Forward");
          break;
        }
      case Control::Backward: {
          backward();
          Serial.println("Backward");
          break;
        }
      case Control::Left: {
          left();
          Serial.println("Left");
          break;
        }
      case Control::Right: {
          right();
          Serial.println("Right");
          break;
        }
      case Control::Off: {
          off();
          Serial.println("Stop");
          break;
        }
    }
    IrReceiver.resume();
  }
}