#include "connection.hh"

namespace {

/// Connection timeout in msecs
constexpr int timeout = 4000;

} //namespace

Connection::Connection(QObject* parent) : QObject(parent)
{
}

QString Connection::socketError() const
{
    return socket_.errorString();
}

bool Connection::connect(const QString& serverName)
{
    socket_.connectToServer(serverName);

    if(!socket_.waitForConnected(timeout))
        return false;

    return true;
}

bool Connection::sendMessage(const Message& message)
{
    if (!socket_.isOpen())
        return false;

    QByteArray block;
    QDataStream stream(&block, QIODevice::WriteOnly);
    stream.setVersion(QDataStream::Qt_5_0);

    stream << (quint16)0;
    stream << serializeMessage(message).toLatin1();
    stream.device()->seek(0);
    stream << (quint16)(block.size() - sizeof(quint16));

    socket_.write(block);

    if(!socket_.waitForBytesWritten(timeout))
        return false;

    return true;
}

Message Connection::readMessage()
{
    if(!socket_.waitForReadyRead(timeout)) {
        Message message;
        message.type = MessageType::Invalid;
        return message;
    }

    quint16 bytesToRead = 0;
    {
        QDataStream stream(&socket_);
        stream.setVersion(QDataStream::Qt_5_0);
        stream >> bytesToRead;
    }

    QByteArray block;
    block.append(socket_.readAll());

    while(socket_.waitForReadyRead(0))
        block.append(socket_.readAll());

    QString messageText;
    {
        QDataStream stream(&block, QIODevice::ReadOnly);
        stream.setVersion(QDataStream::Qt_5_0);
        QByteArray data;
        stream >> data;
        messageText = QString::fromLatin1(data);
    }

    return parseMessage(messageText);
}
