// TODO
// --> Function that returns a position the moon is in

// --> Function that moves the motor to the position
//    --> Function that moves steps (done)
//    --> Function that returns how many steps to move
//      --> Function that returns the current position
#include <Wire.h>
#include <RTClib.h>

RTC_DS1307 RTC;

// Define motor pins
#define A_OUT_1 9
#define A_OUT_2 10
#define B_OUT_1 11
#define B_OUT_2 12

// Define the delay between steps in milliseconds
const int STEP_DELAY = 200; // Adjust for speed
int stepsMoved = 0;

// Define the step sequence for a bipolar stepper motor
const int stepSequence[4][4] = {
  {HIGH, LOW, HIGH, LOW},  // Step 1
  {LOW, HIGH, HIGH, LOW},  // Step 2
  {LOW, HIGH, LOW, HIGH},  // Step 3
  {HIGH, LOW, LOW, HIGH}   // Step 4
};

// Moon Constants Global Variables
const float FULL_MOON_CYCLE_DAYS = 29.53;
const float MOTOR_STEPS_PER_REV = 200;
const float DEGREES_PER_STEP = 360 / FULL_MOON_CYCLE_DAYS;

// Modes
enum Mode {MOON_MODE, DEMO_MODE};
Mode CurrentMode = MOON_MODE;

// Moon Mode Variables
float currentMoonPhase = 15;
float targetDegrees = 0;
int targetSteps = 0;
String nextFullMoon = "";

int MoonPhase () {
  // Age of the moon phase from 0 - 7
  // 0 is full moon, 4 is new moon
  DateTime now = RTC.now();
  double julianDate = 0;
  double elapsedDays = 0; // days elapsed since the full moon
  int moonPhase = 0;
  julianDate = JulianDate(now.year(), now.month(), now.day());
  julianDate = int(julianDate - 2244116.75);
  julianDate /= 29.53;
  julianDate -= moonPhase;
  elapsedDays = julianDate * 29.53;
  nextFullMoon = String((int(29.53 - elapsedDays)));
  moonPhase = julianDate*8 + 0.5;
  moonPhase = moonPhase & 7;
  return moonPhase;
}

double JulianDate(int y, int m, int d){
  // Converts date to a Julian Date
  int mm, yy;
  double k1, k2, k3;
  double j;

  yy = y - int ((12-m)/10);
  mm = m+9;
  if (mm >= 12){
    mm = mm-12;
  }
  k1 = 365.25 * (yy + 4172);
  k2 = int((30.6001 * mm) + 0.5);
  k3 = int((((yy/100) + 4) * 0.75) - 38);
  j = k1 + k2 + d + 59;
  j = j - k3;

  return j; 
}


void setup() {
  // Initialize serial communication
  Serial.begin(9600); // Set baud rate to 9600
  RTC.begin();
  if (! RTC.isrunning()){
    Serial.println("RTC not running");
  }

  RTC.adjust(DateTime(2024, 12, 1, 22, 32, 10));

  Wire.begin();

  // Set motor pins as outputs
  pinMode(A_OUT_1, OUTPUT);
  pinMode(A_OUT_2, OUTPUT);
  pinMode(B_OUT_1, OUTPUT);
  pinMode(B_OUT_2, OUTPUT);

  // Move the motor 50 steps forward
  //stepsMoved = moveSteps(50); // Call moveSteps

  //delay(1000); // Pause for 1 second

  // Move the motor 50 steps backward
  //stepsMoved = moveSteps(-50); // Call moveSteps
  //delay(1000); // Pause for 1 second

  //Serial.println(MoonPhase());
}


void loop() {
  // Do nothing
  stepsMoved = moveSteps(50);
}

// Function to move the motor a specific number of steps
int moveSteps(int steps) {
  int stepCount = abs(steps);          // Get the absolute number of steps
  int direction = (steps > 0) ? 1 : -1; // Determine direction (1 = forward, -1 = backward)

  int currentStep = 0; // Track current step in the sequence

  for (int i = 0; i < stepCount; i++) {
    // Calculate the next step index
    currentStep = (currentStep + direction + 4) % 4;

    // Set the motor coils according to the step sequence
    digitalWrite(A_OUT_1, stepSequence[currentStep][0]);
    digitalWrite(A_OUT_2, stepSequence[currentStep][1]);
    digitalWrite(B_OUT_1, stepSequence[currentStep][2]);
    digitalWrite(B_OUT_2, stepSequence[currentStep][3]);

    // Delay to control the speed
    delay(STEP_DELAY);
  }

  // Turn off all coils after motion
  releaseMotor();
  return stepCount; // Return the number of steps moved
}

// Function to release the motor (turn off all coils)
void releaseMotor() {
  digitalWrite(A_OUT_1, LOW);
  digitalWrite(A_OUT_2, LOW);
  digitalWrite(B_OUT_1, LOW);
  digitalWrite(B_OUT_2, LOW);
}