#include <LedControl.h>
#include <elapsedMillis.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Encoder pins
const int clkPin = 8;
const int dtPin = 9;
const int swPin = 6;

// Switch on pin 4 to start/stop the sequencer
const int switchPin = 4;


Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire);
byte compteur;

elapsedMillis timeElapsed;

const int CHANNEL = 1;
const int CONTNUM = 11;
const int running = 1;
const int stopped = 0;
const int REDLED = 7;
const int STOMP = 2;

boolean EXT_CLOCK = false;

unsigned int interval = 120;
byte data;
byte midi_start = 0xfa;
byte midi_stop = 0xfc;
byte midi_clock = 0xf8;
byte midi_continue = 0xfb;
int midi_state = running;
int tock = 0;
int tick_counter = 0;
int prog[16] = {8, 8, 2, 2, 2, 2, 8, 8, 2, 2, 2, 2, 8, 8, 2, 2};
int pitch[16] = {127, 0, 127, 0, 127, 0, 127, 0, 127, 0, 127, 0, 127, 0, 127, 127};
int i = 0;
int y = 0;
int x = 0;
int speed = 80;
LedControl lc = LedControl(12, 11, 10, 1);

int buttons[8] = {2, 3, 4, 5, 6, 7, 8, 9};
int step = 0;
int posi = 0;
int patern[16] = {-3, -3, -3, -3, 3, 3, 3, 3};

// Variables for the encoder
int currentStateCLK;
int previousStateCLK;
int encoderPos = 0;
bool encoderPressed = false;

// Debouncing for the switch
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 200;  // Adjust this if needed
bool lastSwitchState = HIGH;  // The previous state of the switch
bool isRunning = false;  // Track if the sequencer is running
bool buttonPressed = false;  // Track if the button has been pressed

void setup() {
  // Initialize the LED control
  lc.shutdown(0, false);
  lc.setIntensity(0, 8);
  lc.clearDisplay(0);

  for (int i = 0; i < 8; i++) {
    pinMode(buttons[i], INPUT_PULLUP);
  }

  // Initialize the OLED display
  Serial.begin(9600);
  Serial.println("OLED initialized");
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x32
  display.display();
  delay(1000);
  display.clearDisplay();
  display.display();
  display.setTextSize(1);
  display.setTextColor(WHITE);

  // Set up encoder pins
  pinMode(clkPin, INPUT);
  pinMode(dtPin, INPUT);
  pinMode(swPin, INPUT_PULLUP); // Pull-up resistor for the switch

  // Read the initial state of the encoder CLK pin
  previousStateCLK = digitalRead(clkPin);

  // Set up the switch pin
  pinMode(switchPin, INPUT_PULLUP); // Pull-up for the start/stop switch
}

void loop() {
  // Handle the start/stop switch
  checkSwitch();  // Improved debounce logic

  if (isRunning) {
    // Your sequencer logic, encoder handling, and display updates here
    posi = patern[step];
    for (int i = 0; i < 8; i++) {
      for (int y = 1; y < (posi + 5); y++) {
        lc.setLed(0, y, step, true);
      }
      lc.setLed(0, 0, step, true);
    }

    delay(speed);
    lc.clearDisplay(0);

    for (int i = 0; i < 8; i++) {
      for (int y = 1; y < (posi + 5); y++) {
        lc.setLed(0, y, step, true);
      }
      lc.setLed(0, 0, step, false);
    }

    delay(speed);
    lc.clearDisplay(0);

    // OLED display updates
    display.clearDisplay();
    display.setCursor(0, 0);
    display.println("test compteur");
    display.print("compteur: ");
    display.print(encoderPos);  // Display the encoder position on the OLED
    display.display();

    step++;
    if (step == 8) {
      step = 0;
    }
  }
}


void checkSwitch() {
  // Read the current state of the switch
  bool currentSwitchState = digitalRead(switchPin);

  // If the switch has been pressed (changed from HIGH to LOW)
  if (currentSwitchState == LOW && lastSwitchState == HIGH && (millis() - lastDebounceTime) > debounceDelay) {
    // Toggle the sequencer state when the button is pressed
    isRunning = !isRunning;
    if (isRunning) {
      Serial.println("Sequencer started");
    } else {
      Serial.println("Sequencer stopped");
    }
    // Update the last debounce time
    lastDebounceTime = millis();
  }

  // Save the current state for comparison in the next loop
  lastSwitchState = currentSwitchState;
}

void progChange(int newChannel, int prognum) {
  Serial.write(0xC0 | (newChannel - 1));
  Serial.write(prognum);
}

void controlChange(int newChannel, int controlNumber, int controlValue) {
  Serial.write(0xB0 | (newChannel - 1));
  Serial.write(controlNumber);
  Serial.write(controlValue);
}

void syncClock() {
  Serial.write(midi_clock);
}

void stomp_handler() {
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  if (interrupt_time - last_interrupt_time > 200) {
    if (midi_state == running) {
      midi_state = stopped;
    } else {
      midi_state = running;
      i = 0;
      tick_counter = 5;
    }
  }
  last_interrupt_time = interrupt_time;
}