/**
 * @file WsClient.cpp
 */

#include "WsClient.h"

#include <QUrl>

namespace shq {

WsClient::WsClient(QObject* parent) : QObject(parent) {
    connect(&socket_, &QWebSocket::connected,    this, &WsClient::onConnected);
    connect(&socket_, &QWebSocket::disconnected, this, &WsClient::onDisconnected);
    connect(&socket_, &QWebSocket::textMessageReceived,
            this, [this](const QString& s) { Q_EMIT textReceived(s); });
    connect(&socket_, &QWebSocket::binaryMessageReceived,
            this, [this](const QByteArray& b) { Q_EMIT binaryReceived(b); });

    reconnectTimer_.setInterval(3000);
    connect(&reconnectTimer_, &QTimer::timeout, this, &WsClient::onTick);
}

void WsClient::connectTo(const QString& host, uint16_t port) {
    host_ = host;
    port_ = port;
    wantOpen_ = true;
    openSocket();
    reconnectTimer_.start();
}

void WsClient::reconnectTo(const QString& host, uint16_t port) {
    host_ = host;
    port_ = port;
    wantOpen_ = true;
    socket_.abort();           /* drop current; onTick / openSocket reopens */
    openSocket();
    if (!reconnectTimer_.isActive()) { reconnectTimer_.start(); }
}

void WsClient::close() {
    wantOpen_ = false;
    reconnectTimer_.stop();
    socket_.close();
}

void WsClient::openSocket() {
    if (!wantOpen_) { return; }
    if (socket_.state() == QAbstractSocket::ConnectedState ||
        socket_.state() == QAbstractSocket::ConnectingState) {
        return;
    }
    QUrl url;
    url.setScheme("ws");
    url.setHost(host_);
    url.setPort(port_);
    url.setPath("/ws");
    socket_.open(url);
}

void WsClient::onConnected() {
    connected_ = true;
    Q_EMIT connectedChanged(true);
}

void WsClient::onDisconnected() {
    if (connected_) {
        connected_ = false;
        Q_EMIT connectedChanged(false);
    }
}

void WsClient::onTick() {
    if (wantOpen_ && socket_.state() == QAbstractSocket::UnconnectedState) {
        openSocket();
    }
}

void WsClient::sendText(const QString& json) {
    if (socket_.state() == QAbstractSocket::ConnectedState) {
        socket_.sendTextMessage(json);
    }
}

} /* namespace shq */
