#ifndef NXTHARDWAREDEVICEREST_PIMPL_H
#define NXTHARDWAREDEVICEREST_PIMPL_H

#include "nxthardwaredevicerest.h"

#include <QHostAddress>
#include <QTcpSocket>

#if defined(__linux__)
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#else
#include <WinSock2.h>
#include <WS2tcpip.h>
#endif

namespace Nxt {
namespace Internal {

class NxtHardwareDeviceREST::pimpl : public QObject
{
    Q_OBJECT

public:
    pimpl(QString host, NxtHardwareDeviceREST *parent = nullptr);
    pimpl(QString host, QString username, QString password, NxtHardwareDeviceREST *parent = nullptr);
    ~pimpl();

    void setHost(const QString &host) { m_host = QHostAddress(host); }
    void setUsername(const QString &username) { m_username = username; }
    void setPassword(const QString &password) { m_password = password; }
    void setTimeout(int timeout_sec) { m_timeout_sec = timeout_sec; }

    bool available();
    int authenticate();
    QJsonObject deviceInfo();
    bool testVApp(const QString& name);
    bool startVApp(const QString& name);
    bool startVAppInGdbServer(const QString& name);

protected:
    QHostAddress m_host;
    QString m_username;
    QString m_password;
    unsigned short m_port = 80;
    int m_timeout_sec = 3;

    bool connect();
    bool quit();

    bool socketReceive(const QByteArray &request, char *buffer, const int bufferLength);
    int socketInit();
    int socketQuit();
#if defined(__linux__) || defined(__MINGW32__)
    QTcpSocket m_socket;
#else
    int socketClose(SOCKET m_socket);
#endif

#if defined(__linux__) || defined(__MINGW32__)
    // todo
#else
    SOCKET m_socket;
    SOCKADDR_IN m_remote;
#endif
    const QString http_version = "HTTP/1.1";

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

} // namespace Internal
} // namespace Nxt

#endif // NXTHARDWAREDEVICEREST_PIMPL_H
