/*******************************************************************************
  Copyright(c) 2015,2020 Camiel Severijns. All rights reserved.

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
 License version 2 as published by the Free Software Foundation.
 .
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Library General Public License for more details.
 .
 You should have received a copy of the GNU Library General Public License
 along with this library; see the file COPYING.LIB.  If not, write to
 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.
*******************************************************************************/

#pragma once

#include "indifocuser.h"

class SmartFocus : public INDI::Focuser
{
  public:
    SmartFocus();

    const char *getDefaultName() override;

    bool initProperties() override;
    bool updateProperties() override;

    virtual bool Handshake() override;

    virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override;
    //virtual bool ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n) override;

    virtual bool AbortFocuser() override;
    virtual IPState MoveAbsFocuser(uint32_t targetPosition) override;
    virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override;
    virtual void TimerHit() override;

    typedef unsigned short Position;
  protected:
    virtual bool saveConfigItems(FILE *fp) override;

  private:
    typedef unsigned char Flags;

    enum State
    {
        Idle,
        MovingTo,
        MovingIn,
        MovingOut
    };

    enum StatusFlags
    {
        STATUS_SERIAL_FRAMING_ERROR = 0,
        STATUS_SERIAL_OVERRUN_ERROR,
        STATUS_MOTOR_ENCODE_ERROR,
        STATUS_AT_ZERO_POSITION,
        STATUS_AT_MAX_POSITION,
        STATUS_NUM_FLAGS
    };

    enum FlagBits
    {
        SerFramingError   = 0x02,
        SerOverrunError   = 0x04,
        MotorEncoderError = 0x08,
        AtZeroPosition    = 0x40,
        AtMaxPosition     = 0x80
    };

    bool SFacknowledge();
    bool SFisIdle() const { return (state == Idle); }
    bool SFisMoving() const { return !SFisIdle(); }
    Position SFgetPosition();
    Flags SFgetFlags();
    void SFgetState();

    bool send(const char *command, const size_t nbytes, const char *from, const bool log_error = true);
    bool recv(char *respons, const size_t nbytes, const char *from, const bool log_error = true);

    Position position { 0 };
    State state { Idle };
    int timer_id { 0 };

    ILight FlagsL[5];
    ILightVectorProperty FlagsLP;
    INumber MotionErrorN[1];
    INumberVectorProperty MotionErrorNP;
};
