#include <Servo.h>

const uint8_t startButtonPin = A1;
const uint8_t servoPin = 3;

enum ePlayStates
{
  ST_WAIT_START = 0,      //waiting for the START button
  ST_INTRO,               //the intro
  ST_RUN_GAME,            //the actual game
  ST_SHOW_RESULTS          //show results for a period before going back to attract mode
};

Servo servo1;

int arrowCenterPosition = 90,
    arrowSpeed = 20,
    numberOfSweeps = 0,
    previousNumber = arrowCenterPosition,
    nextNumber = arrowCenterPosition;

//randon int gave too may naughties so I am weighing this nice heavy (more odds)
int sweepArray[10] = {7, 4, 5, 6, 9, 6, 7, 4, 5, 5, 7};

void setup() {
  pinMode(startButtonPin, INPUT_PULLUP);
  servo1.attach(servoPin);
  servo1.write(arrowCenterPosition);

  //random number used to pick actions
  randomSeed(A0);

  Serial.begin(9600);
}

void loop() {
  static uint8_t
  gameState = ST_WAIT_START;

  switch (gameState)
  {
    case    ST_WAIT_START:
      if (bCheckStartResetButton())
      {
        gameState = ST_INTRO;
      }//if

      break;
    case    ST_INTRO:
      //center arrow
      servo1.write(arrowCenterPosition);

      //use a sweepArray so we have weigh things more nice than a random()
      numberOfSweeps = sweepArray[random(0, 10)];

      Serial.println(numberOfSweeps);
      previousNumber = arrowCenterPosition;
      nextNumber = arrowCenterPosition;
      gameState = ST_RUN_GAME;

      break;
    case    ST_RUN_GAME:
      playGame();
      gameState = ST_SHOW_RESULTS;

      break;
    case    ST_SHOW_RESULTS:
      if (nextNumber < 90)
      {
        Serial.println("naughty");
      }
      else {
        Serial.println("nice");
      }
      gameState = ST_WAIT_START;

      break;
  }//switch
}//loop

void playGame()
{
  for (int i = 0; i <= numberOfSweeps; i++) {
    previousNumber = nextNumber;
    nextNumber = getRandomNumber(previousNumber);
    sweepMotor(previousNumber, nextNumber);
  }
}

void sweepMotor(int currentPosition, int newPosition)
{
  int loopCount = 0;
  arrowSpeed = 20;
  //determine if we are going left or right
  if (currentPosition < newPosition)
  {
    int fullChangeDifference = newPosition - currentPosition;
    int centerOfFullDistance = fullChangeDifference / 2;
    //inside loop keep a count, every X loops we add or subtract from arrowSpeed

    for (int pos = currentPosition; pos <= newPosition; pos += 1) {
      loopCount++;
      if ((loopCount % 3) == 0)
      {
        Serial.println(arrowSpeed);
        //if less than half way, speed up
        if (pos < (currentPosition + centerOfFullDistance))
        {
          arrowSpeed = arrowSpeed - 1;
        }
        else {
          arrowSpeed = arrowSpeed + 1;
        }
        //make sure I dont go under 0
        if (arrowSpeed > 1000 || arrowSpeed <= 0)
        {
          arrowSpeed = 1;
        }
      }
      servo1.write(pos);
      delay(arrowSpeed);
    }
  }
  else {
    int fullChangeDifference = currentPosition - newPosition;
    int centerOfFullDistance = fullChangeDifference / 2;

    for (int pos = currentPosition; pos >= newPosition; pos -= 1) {
      loopCount++;
      if ((loopCount % 3) == 0)
      {
        //if less than half way, speed up
        if (pos < (currentPosition - centerOfFullDistance))
        {
          arrowSpeed = arrowSpeed + 1;
        }
        else {
          arrowSpeed = arrowSpeed - 1;
        }
        //make sure I dont go under 0
        if (arrowSpeed > 1000 || arrowSpeed <= 0)
        {
          arrowSpeed = 1;
        }
      }
      servo1.write(pos);
      delay(arrowSpeed);
    }
  }
}

int getRandomNumber(int lastPosition)
{
  if (lastPosition >= 90)
  {
    //naughty degrees
    return random(20, lastPosition);
  }
  else {
    //nice degrees
    return random(lastPosition, 161);
  }
}

bool bCheckStartResetButton( void )
{
  static uint8_t
  lastSR;
  static uint32_t
  tSR = 0ul;
  uint32_t
  tNow = millis();

  //update the start/reset every 50mS
  if ( tNow - tSR < 50ul )
    return false;

  //standard logic for button becoming pressed...
  tSR = tNow;
  uint8_t nowSR = digitalRead( startButtonPin );
  if ( nowSR != lastSR )
  {
    lastSR = nowSR;
    if ( nowSR == LOW )
    {
      return true;        //return true if the switch became pressed
    }
  }//if

  //not pressed so return false
  return false;
}//bCheckStartResetButton