#ifndef PLUNGER_H
#define PLUNGER_H

#include <Streaming.h>
#include <Controllino.h>

#include "config.h"
#include "Addon.h"
#include "common/macros.h"
#include "config.h"
#include "types.h"
#include "./components/CurrentSensor.h"

class Plunger : public Addon
{
public:
  class LimitSwitch
  {
  public:
    LimitSwitch(short _pin) : pin(_pin),
                              ts(0){};
    bool value;
    byte pin;
    millis_t ts;
    void loop()
    {
      if (millis() - ts > LIMIT_SWITCH_INTERVAL)
      {
        value = analogRead(pin) > 700 ? true : false;
        ts = millis();
      }
    }
    void setup()
    {
      pinMode(pin, INPUT);
    }
  };

  enum E_PLUNGER_STATE
  {
    NONE = 0,
    PLUNGING = 100,
    STOPPED = 200,
    HOMING = 300,
    RETRACT = 350,
    MANUAL = 360,
    ERROR = 400
  };

  enum P_FLAGS
  {
    INITIATED = 1,
    MOVING = 2,
    RETRACTING = 3,
    RETRACTED = 4,
    FREEING = 5,
    DONE = 6,
    PAUSED = 7
  };

  Plunger(short _limitUp,
          short _limitDown,
          short _motorDirPin,
          short _motorStepPin,
          short _motorStepPinFast,
          short _motorAlarmPin,
          short _motorPowerPin,
          millis_t _plungeTimeout,
          millis_t _homeTimeout,
          Addon *owner,
          AddonFnPtr _cb) : Addon(PLUNGER_STR, PLUNGER),
                            _state(NONE),
                            _last_state(NONE),
                            u1(LimitSwitch(_limitUp)),
                            l1(LimitSwitch(_limitDown)),
                            motorDirPin(_motorDirPin),
                            motorStepPin(_motorStepPin),
                            motorStepPinFast(_motorStepPinFast),
                            motorAlarmPin(_motorAlarmPin),
                            motorPowerPin(_motorPowerPin),
                            plungeTimeout(_plungeTimeout),
                            homeTimeout(_homeTimeout),
                            owner(owner),
                            onChange(_cb)
  {
    // setFlag(DEBUG);
  }
#ifdef HAS_STATES
  String state();
#endif
  void debug(Stream *stream);
  
  void info(Stream *stream)
  {
    //*stream << this->name;
  }

  short setup();
  short loop();

  short plunge(short val = 0);
  short home(short val = 0);
  short test(short val = 0);
  short retract();
  void zero();
  short reset(short val = 0);
  short stop(short val = 0);
  bool pause();
  bool resume();
  short goToPos(long pos, long speed);
  short moveMotor1(short val = 0);
  short moveMotor2(short val = 0);
  short moveMotors(short val = 0);
  short setSpeed(short val = 0);
  short move(short dir);
  short moveFast(short dir);

  LimitSwitch u1;
  LimitSwitch l1;

private:
  short _last_state;
  bool change(short newState);
  long positions[2];

  AddonFnPtr onChange;
  Addon *owner;
  short pFlags;
  bool retracting;
  short _state;
  float speed;

  millis_t plungeTimeout;
  millis_t homeTimeout;

  millis_t plungeStartTS;
  millis_t homeStartTS;
  
  short motorStepPin;
  short motorStepPinFast;
  short motorDirPin;
  short motorAlarmPin;
  short motorPowerPin;

protected:
};

#endif

