#include <DigiMouse.h>

/**
 * Does lots clicks, when pedal is pushed.
 * click/sec depends on potentiometer region.
 */

#define P0 0
#define P2 2
#define AP2 1
#define P1 1

#define LED_BUILTIN P1

#define BOUNCE_MS 5

#define BOUNCING_ON 1
#define BOUNCING_ALREADY_ON 2
#define BOUNCING_OFF -1
#define BOUNCING_ALREADY_OFF -2

int region[] = {
  867,
  752,
  620,
  483,
  346,
  235,
  100,
  1
};

int clickPerSec[] = {
  50,
  40,
  30,
  15,
  5,
  -5,
  -10,
  -15,
  -20
};

byte lastRegion = -1;
unsigned long lastClick = 0;
unsigned long clickMs = 100;
boolean left = true;
unsigned long lastLedOn = 0;
boolean buttonOn = true;
char bouncing = BOUNCING_ALREADY_OFF;
unsigned long lastBouncingStart = 0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(P0, INPUT_PULLUP);
  pinMode(P2, INPUT);
  DigiMouse.begin();
}

void loop() {
  unsigned long now = millis();
  if((digitalRead(P0) == LOW) || (bouncing == BOUNCING_ON))
  {
    // -- Pushing the pedal
    if(smallerCheckOverflow(lastClick, clickMs, now))
    {
//      digitalWrite(LED_BUILTIN, HIGH);
      // Time to click
      if(left)
      {
        DigiMouse.setButtons(1<<0); //left click
      }
      else
      {
        DigiMouse.setButtons(1<<1); //right click
      }
      buttonOn = true;
      lastClick = now;
    }
    else if(buttonOn && smallerCheckOverflow(lastClick, clickMs / 2, now))
    {
//      digitalWrite(LED_BUILTIN, LOW);
      DigiMouse.setButtons(0); // unclick
      buttonOn = false;
    }

    if(bouncing == BOUNCING_ALREADY_OFF) 
    {
      bouncing = BOUNCING_ON;
      lastBouncingStart = now;
    }
    else if((bouncing == BOUNCING_ON) && smallerCheckOverflow(lastBouncingStart, BOUNCE_MS, now))
    {
      bouncing = BOUNCING_ALREADY_ON;
    }
  }
  else
  {
    if(bouncing == BOUNCING_ALREADY_ON) 
    {
      bouncing = BOUNCING_OFF;
      lastBouncingStart = now;
    }
    else if((bouncing == BOUNCING_OFF) && smallerCheckOverflow(lastBouncingStart, BOUNCE_MS, now))
    {
      bouncing = BOUNCING_ALREADY_OFF;
    }
    if(buttonOn)
    {
      DigiMouse.setButtons(0); // unclick for sure
//      digitalWrite(LED_BUILTIN, LOW);
      buttonOn = false;
    }

    int val = analogRead(AP2);
    byte activeRegion = 8;
    for(int i = 0; i < 8 ; i++)
    {
      if(val > region[i])
      {
        activeRegion = i;
        break;
      }
    }
    if(activeRegion != lastRegion)
    {
//      digitalWrite(LED_BUILTIN, HIGH);
      lastRegion = activeRegion;
      int currentCps = clickPerSec[activeRegion];
      clickMs = 1000UL / (unsigned long)abs(currentCps);
      if (currentCps < 0) {
        left = false;
      }
      else
      {
        left = true;
      }
    }
    if(smallerCheckOverflow(lastLedOn, clickMs * 2, now))
    {
      digitalWrite(LED_BUILTIN, left);
      lastLedOn = now;
    }
    if(smallerCheckOverflow(lastLedOn, clickMs / 3, now))
    {
      digitalWrite(LED_BUILTIN, !left);
    }
  }
  DigiMouse.update();
}

boolean smallerCheckOverflow(unsigned long prevMillis, unsigned long diff, unsigned long currentMillis)
{
  if ((prevMillis <= currentMillis) && ((prevMillis + diff) <= prevMillis))
  // -- current does not overflows, but pref+diff does
  {
    return false;
  }
  return prevMillis + diff <= currentMillis;
}
