#ifndef VFD_H
#define VFD_H

#include <Streaming.h>
#include "./Addon.h"
#include "./enums.h"
#include "./config.h"

class VFD : public Addon
{
public:
    enum DIRECTION
    {
        FORWARD = 2,
        STOP = 0,
        REVERSE = 1
    };

    VFD(
        int _freqInputPort,
        int _freqOutputPort) : Addon(VFD_STR, VFD_CONTROL),
                               inputFreqPort(_freqInputPort),
                               outputFreqPort(_freqOutputPort),
                               direction(STOP){
                                   // setFlag(DEBUG);
                               };

    void rev(short nop)
    {
        update(DIRECTION::REVERSE);
        return E_OK;
    }

    void fwd(short nop)
    {
        update(DIRECTION::FORWARD);
        return E_OK;
    }

    short setup()
    {
        pinMode(FWD_PIN, OUTPUT);
        pinMode(REV_PIN, OUTPUT);
        pinMode(inputFreqPort, INPUT);
        stop();
        return E_OK;
    }

    short stop(short nop = 0)
    {
        update(DIRECTION::STOP);
        return E_OK;
    }

    void speed(int aValue)
    {
        // aValue = clamp<int>(aValue, 0, 255);
        // analogWrite(freqPin, aValue);
        // Serial.println("set speed");
        // Serial.println(aValue);
    }

    virtual void debug(Stream *stream)
    {
        *stream << this->name << ":" << SPACE(direction) << SPACE("Input Freq") << inputFreq;
    }

    virtual void info(Stream *stream)
    {
        // *stream << this->name << "\n\t" << SPACE(": FWD PIN " << FWD_PIN << " | REV PIN " << REV_PIN);
    }

    uchar direction;
    uchar lastDirection;
    millis_t dt;

private:
    int inputFreqPort;
    int outputFreqPort;

    ushort inputFreq;

    short loop()
    {
        if (now - last > ANALOG_READ_INTERVAL)
        {
            if (inputFreqPort)
            {
                inputFreq = clamp<ushort>(analogRead(inputFreqPort), 0, 255);
            }

            last = now;
        }
        return E_OK;
    }

    void update(uchar newDirection)
    {
        if (direction != newDirection)
        {
            dt = now;
            lastDirection = direction;
            direction = newDirection;
            switch (direction)
            {
            case DIRECTION::FORWARD:
            {
                digitalWrite(REV_PIN, LOW);
                digitalWrite(FWD_PIN, HIGH);
                break;
            }
            case DIRECTION::REVERSE:
            {
                digitalWrite(FWD_PIN, LOW);
                digitalWrite(REV_PIN, HIGH);
                break;
            }
            case DIRECTION::STOP:
            {
                digitalWrite(FWD_PIN, LOW);
                digitalWrite(REV_PIN, LOW);
            }
            }
        }
    }
};

#endif
