
#include <AccelStepper.h>
#include "<MultiStepper.h>"

#define MAX_ACCELERATION 1000
#define MAX_SPEED 1000
#define POT_PIN_SPEED 0
#define ANALOG_START_THRESHOLD 600
#define ANALOG_STOP_THRESHOLD 400
#define PIN_LED_ON 2
#define PIN_LED_OFF 3

struct MotorInfo {
  uint8_t dirPin;
  uint8_t pulsePin;
  uint8_t potPin;
};

class StepperMotorController {
  private:
    MotorInfo _motors[6];
    uint8_t _count;
    MultiStepper _steppers;
    int _speedPotValue;

  public:
    StepperMotorController(MotorInfo *motors, uint8_t count) : _count(count) {
      for (uint8_t i = 0; i < count; ++i) {
        _motors[i] = motors[i];
        AccelStepper stepper = AccelStepper(AccelStepper::DRIVER, _motors[i].pulsePin, _motors[i].dirPin);
        stepper.setMaxSpeed(MAX_SPEED);
        stepper.setAcceleration(MAX_ACCELERATION);
        _steppers.addStepper(stepper);
      }
    }

    float getMotorSpeed(uint8_t index) {
      return _steppers.getSpeed(index);
    }

    void loop() {
      _speedPotValue = analogRead(POT_PIN_SPEED);
      for (uint8_t i = 0; i < _count; ++i) {
        int potValue = analogRead(_motors[i].potPin);
        float speed = (potValue / 1023.0) * _speedPotValue;
        _steppers.setSpeed(i, speed);
      }
      _steppers.runSpeedToPosition();
    }
};

class MotorController {
  private:
    StepperMotorController _stepperController;

  public:
    MotorController(MotorInfo *motors, uint8_t count) : _stepperController(motors, count) {
        pinMode(PIN_LED_ON, OUTPUT);
        pinMode(PIN_LED_OFF, OUTPUT);
    }

    void loop() {
      int startValue = analogRead(PIN_LED_ON);
      int stopValue = analogRead(PIN_LED_OFF);
      if (startValue > ANALOG_START_THRESHOLD) {
        digitalWrite(PIN_LED_ON, HIGH);
        _stepperController.loop();
      } else if (stopValue > ANALOG_STOP_THRESHOLD) {
        digitalWrite(PIN_LED_OFF, HIGH);
      } else {
        digitalWrite(PIN_LED_ON, LOW);
        digitalWrite(PIN_LED_OFF, LOW);
      }
      delay(10);
    }
};

MotorInfo motors[] = {
  {12, 13, 1},
  {10, 11, 2},
  {8, 9, 3},
  {6, 7, 4},
  {4, 5, 5},
  {2, 3, 6}
};

MotorController controller(motors, 6);

void setup() {}

void loop() {
  controller.loop();
}
