#ifndef RESTCONNECTION_PIMPL_H
#define RESTCONNECTION_PIMPL_H

#include "restconnection.h"

#include <QTcpSocket>
#include <QTimer>

namespace Nxt {
namespace Internal {

enum RestStateInternal {
    SocketUnconnected,
    SocketConnecting,
    SocketConnected,
    UserAuthRequested,
    UserAuthenticated,
    ConnectionEstablished
};

class RestConnection::pimpl : public QObject
{
    Q_OBJECT
    friend class RestConnection;

public:
    pimpl(RestConnection *parent = nullptr);
    ~pimpl();

    void authenticate();
    void connectToHost();
    void closeConnection(RestError restError, RestError userError, const QByteArray &serverErrorString, const QString &userErrorString);

    RestStateInternal state() const { return m_state; }
    RestError errorState() const { return m_error; }
    QString errorString() const { return m_errorString; }

signals:
    void authenticated(int httpStatusCode);
    void connected();
    void disconnected();
    void dataAvailable(const QString &message);
    void error(RestError);

protected slots:
    void handleSocketConnected();
    void handleSocketError();
    void handleSocketDisconnected();
    void handleStateChanged();
    void handleIncomingData();
    void handleTimeout();

protected:
    void sendData(const QByteArray &data);
    bool canUseSocket() const;

    bool validHttpVersion(const QString &response);
    int getHttpStatusCode(const QString &response);
    const QString token() const;
    const QString tokenBase64() const;
    const QString headerGet(const QString &path) const;
    const QString headerHost() const;
    const QString headerAuth() const;
    const QByteArray toRequest(const QStringList &lines);

    const QString http_version = "HTTP/1.1";
    RestConnection *m_parent;
    QTcpSocket *m_socket;
    RestStateInternal m_state;
    QByteArray m_incomingData;
    RestError m_error;
    QString m_errorString;
    QTimer m_timeoutTimer;
};

} // namespace Internal
} // namespace Nxt

#endif // RESTCONNECTION_PIMPL_H
