#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

SoftwareSerial mp3Serial(10, 11); // RX,TX
DFRobotDFPlayerMini mp3;

// Encoder
#define CLK 2
#define DT  3
#define SW  4

int lastCLK;
int volumeLevel = 15;
int currentTrack = 1;
bool playing = false;

unsigned long lastClickTime = 0;
int clickCount = 0;

void drawUI()
{
  oled.clearDisplay();

  oled.setTextSize(1);
  oled.setTextColor(WHITE);

  oled.setCursor(25,0);
  oled.print("MINI MP3 PLAYER");

  oled.drawLine(0,10,128,10,WHITE);

  oled.setCursor(0,18);
  oled.print("TRACK:");
  oled.print(currentTrack);

  oled.setCursor(0,32);
  oled.print("STATUS:");

  if(playing)
    oled.print("PLAY");
  else
    oled.print("PAUSE");

  oled.setCursor(0,48);
  oled.print("VOL");

  oled.drawRect(28,48,80,10,WHITE);

  int bar = map(volumeLevel,0,30,0,78);
  oled.fillRect(29,49,bar,8,WHITE);

  oled.setCursor(112,48);
  oled.print(volumeLevel);

  oled.display();
}

void nextTrack()
{
  currentTrack++;
  mp3.next();
  playing = true;
  drawUI();
}

void prevTrack()
{
  if(currentTrack > 1)
    currentTrack--;

  mp3.previous();
  playing = true;
  drawUI();
}

void togglePlay()
{
  if(playing)
  {
    mp3.pause();
    playing = false;
  }
  else
  {
    mp3.start();
    playing = true;
  }

  drawUI();
}

void setup()
{
  Serial.begin(9600);

  pinMode(CLK, INPUT_PULLUP);
  pinMode(DT, INPUT_PULLUP);
  pinMode(SW, INPUT_PULLUP);

  lastCLK = digitalRead(CLK);

  Wire.begin();

  if(!oled.begin(SSD1306_SWITCHCAPVCC,0x3C))
  {
    while(1);
  }

  oled.clearDisplay();
  oled.setTextSize(2);
  oled.setCursor(10,20);
  oled.print("MP3");
  oled.display();

  delay(1000);

  mp3Serial.begin(9600);

  if(mp3.begin(mp3Serial))
  {
    mp3.volume(volumeLevel);
    delay(200);
    mp3.play(1);
    playing = true;
  }

  drawUI();
}

void loop()
{
  // Encoder rotation
  int currentCLK = digitalRead(CLK);

  if(currentCLK != lastCLK && currentCLK == LOW)
  {
    if(digitalRead(DT) != currentCLK)
    {
      volumeLevel++;
      if(volumeLevel > 30)
        volumeLevel = 30;
    }
    else
    {
      volumeLevel--;
      if(volumeLevel < 0)
        volumeLevel = 0;
    }

    mp3.volume(volumeLevel);
    drawUI();
  }

  lastCLK = currentCLK;

  // Button handling
  static bool buttonState = HIGH;
  static unsigned long pressStart = 0;

  bool currentButton = digitalRead(SW);

  if(buttonState == HIGH && currentButton == LOW)
  {
    pressStart = millis();
  }

  if(buttonState == LOW && currentButton == HIGH)
  {
    unsigned long duration = millis() - pressStart;

    if(duration > 800)
    {
      nextTrack();
    }
    else
    {
      clickCount++;
      lastClickTime = millis();
    }
  }

  buttonState = currentButton;

  if(clickCount == 1 &&
     millis() - lastClickTime > 400)
  {
    togglePlay();
    clickCount = 0;
  }

  if(clickCount >= 2)
  {
    prevTrack();
    clickCount = 0;
  }
}
