/*
    INDI alpaca Driver

    Copyright (C) 2026 Gord Tulloch

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#pragma once

#include <inditelescope.h>
#include <memory>
#include <vector>
#include <httplib.h>

#ifdef _USE_SYSTEM_JSONLIB
#include <nlohmann/json.hpp>
#else
#include <indijson.hpp>
#endif

class alpacaTelescopeDriver : public INDI::Telescope
{
    public:
        alpacaTelescopeDriver();
        virtual ~alpacaTelescopeDriver() = default;

        virtual const char *getDefaultName() override;
        virtual bool initProperties() override;
        virtual bool updateProperties() override;
        virtual bool Connect() override;
        virtual bool Disconnect() override;
        virtual bool ReadScopeStatus() override;

    protected:
        // Connection
        virtual bool Handshake() override;

        // Telescope Operations
        virtual bool Goto(double ra, double dec) override;
        virtual bool Sync(double ra, double dec) override;
        virtual bool Abort() override;

        // Parking
        virtual bool Park() override;
        virtual bool UnPark() override;
        virtual bool SetCurrentPark() override;

        // Tracking
        virtual bool SetTrackEnabled(bool enabled) override;
        virtual bool SetTrackMode(uint8_t mode) override;
        virtual bool SetTrackRate(double raRate, double deRate) override;

        // Motion Control
        virtual bool MoveNS(INDI_DIR_NS dir, TelescopeMotionCommand command) override;
        virtual bool MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) override;

        // Save configuration
        virtual bool saveConfigItems(FILE *fp) override;

        // Site location
        virtual bool updateLocation(double latitude, double longitude, double elevation) override;

        // Time
        virtual bool updateTime(ln_date *utc, double utc_offset) override;

    private:
        // State tracking
        double m_currentRA { 0 };
        double m_currentDEC { 90 };
        double m_currentAz { 180 };
        double m_currentAlt { 0 };
        double m_targetRA { 0 };
        double m_targetDEC { 0 };
        double m_sinLat, m_cosLat;
        bool isParked{false};
        bool isSlewing{false};
        bool isTracking{false};
        double currentSlewRate{0.5};  // Current slew rate in deg/sec

        // Async slew support: prefer /slewtotargetasync over the blocking /slewtotarget
        bool m_CanSlewAsync{false};

        // Track modes: maps an index in TrackModeSP to the corresponding Alpaca
        // DriveRate value (0=Sidereal, 1=Lunar, 2=Solar, 3=King) reported by /trackingrates
        std::vector<int> m_TrackModeAlpacaRates;

        // Custom tracking rate support (TELESCOPE_HAS_TRACK_RATE)
        bool m_CanSetRaRate{false};
        bool m_CanSetDecRate{false};

        // used by GoTo and Park
        void StartSlew(double ra, double dec, TelescopeStatus status);

        unsigned int DBG_SCOPE { 0 };

        // Scope type and alignment
        INDI::PropertySwitch mountTypeSP {2};
        enum
        {
            ALTAZ,
            EQ_FORK
        };

        // HTTP client for Alpaca communication
        std::unique_ptr<httplib::Client> httpClient;
        int m_DeviceNumber{0};
        int m_ClientID;
        int m_TransactionID{0};

        // Device info properties
        INDI::PropertyText DeviceInfoTP {4};
        enum { DESCRIPTION, DRIVER_INFO, DRIVER_VERSION, INTERFACE_VERSION };

        // Alpaca helper methods
        std::string getAlpacaURL(const std::string& endpoint);
        int getTransactionId()
        {
            return ++m_TransactionID;
        }
        bool sendAlpacaGET(const std::string& endpoint, nlohmann::json& response);
        bool sendAlpacaPUT(const std::string& endpoint, const nlohmann::json& request, nlohmann::json& response);

};
