/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "testhttpserver.h"
#include <QTcpSocket>
#include <QDebug>
#include <QFile>
#include <QTimer>
#include <QTest>
#include <QQmlFile>

/*!
\internal
\class TestHTTPServer
\brief provides a very, very basic HTTP server for testing.

Inside the test case, an instance of TestHTTPServer should be created, with the
appropriate port to listen on.  The server will listen on the localhost interface.

Directories to serve can then be added to server, which will be added as "roots".
Each root can be added as a Normal, Delay or Disconnect root.  Requests for files
within a Normal root are returned immediately.  Request for files within a Delay
root are delayed for 500ms, and then served.  Requests for files within a Disconnect
directory cause the server to disconnect immediately.  A request for a file that isn't
found in any root will return a 404 error.

If you have the following directory structure:

\code
disconnect/disconnectTest.qml
files/main.qml
files/Button.qml
files/content/WebView.qml
slowFiles/slowMain.qml
\endcode
it can be added like this:
\code
TestHTTPServer server;
QVERIFY2(server.listen(14445), qPrintable(server.errorString()));
server.serveDirectory("disconnect", TestHTTPServer::Disconnect);
server.serveDirectory("files");
server.serveDirectory("slowFiles", TestHTTPServer::Delay);
\endcode

The following request urls will then result in the appropriate action:
\table
\header \li URL \li Action
\row \li http://localhost:14445/disconnectTest.qml \li Disconnection
\row \li http://localhost:14445/main.qml \li main.qml returned immediately
\row \li http://localhost:14445/Button.qml \li Button.qml returned immediately
\row \li http://localhost:14445/content/WebView.qml \li content/WebView.qml returned immediately
\row \li http://localhost:14445/slowMain.qml \li slowMain.qml returned after 500ms
\endtable
*/

static QUrl localHostUrl(quint16 port)
{
    QUrl url;
    url.setScheme(QStringLiteral("http"));
    url.setHost(QStringLiteral("127.0.0.1"));
    url.setPort(port);
    return url;
}

TestHTTPServer::TestHTTPServer()
    : m_state(AwaitingHeader)
{
    QObject::connect(&m_server, &QTcpServer::newConnection, this, &TestHTTPServer::newConnection);
}

bool TestHTTPServer::listen()
{
    return m_server.listen(QHostAddress::LocalHost, 0);
}

QUrl TestHTTPServer::baseUrl() const
{
    return localHostUrl(m_server.serverPort());
}

quint16 TestHTTPServer::port() const
{
    return m_server.serverPort();
}

QUrl TestHTTPServer::url(const QString &documentPath) const
{
    return baseUrl().resolved(documentPath);
}

QString TestHTTPServer::urlString(const QString &documentPath) const
{
    return url(documentPath).toString();
}

QString TestHTTPServer::errorString() const
{
    return m_server.errorString();
}

bool TestHTTPServer::serveDirectory(const QString &dir, Mode mode)
{
    m_directories.append(qMakePair(dir, mode));
    return true;
}

/*
   Add an alias, so that if filename is requested and does not exist,
   alias may be returned.
*/
void TestHTTPServer::addAlias(const QString &filename, const QString &alias)
{
    m_aliases.insert(filename, alias);
}

void TestHTTPServer::addRedirect(const QString &filename, const QString &redirectName)
{
    m_redirects.insert(filename, redirectName);
}

void TestHTTPServer::registerFileNameForContentSubstitution(const QString &fileName)
{
    m_contentSubstitutedFileNames.insert(fileName);
}

bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &body)
{
    m_state = AwaitingHeader;
    m_data.clear();

    QFile expectFile(QQmlFile::urlToLocalFileOrQrc(expect));
    if (!expectFile.open(QIODevice::ReadOnly))
        return false;

    QFile replyFile(QQmlFile::urlToLocalFileOrQrc(reply));
    if (!replyFile.open(QIODevice::ReadOnly))
        return false;

    m_bodyData = QByteArray();
    if (body.isValid()) {
        QFile bodyFile(QQmlFile::urlToLocalFileOrQrc(body));
        if (!bodyFile.open(QIODevice::ReadOnly))
            return false;
        m_bodyData = bodyFile.readAll();
    }

    const QByteArray serverHostUrl
        = QByteArrayLiteral("127.0.0.1:")+ QByteArray::number(m_server.serverPort());

    QByteArray line;
    bool headers_done = false;
    while (!(line = expectFile.readLine()).isEmpty()) {
        line.replace('\r', "");
        if (line.at(0) == '\n') {
            headers_done = true;
            continue;
        }
        if (headers_done) {
            m_waitData.body.append(line);
        } else {
            line.replace("{{ServerHostUrl}}", serverHostUrl);
            m_waitData.headers.append(line);
        }
    }
    /*
    while (waitData.endsWith('\n'))
        waitData = waitData.left(waitData.count() - 1);
        */

    m_replyData = replyFile.readAll();

    if (!m_replyData.endsWith('\n'))
        m_replyData.append('\n');
    m_replyData.append("Content-length: ");
    m_replyData.append(QByteArray::number(m_bodyData.length()));
    m_replyData.append("\n\n");

    for (int ii = 0; ii < m_replyData.count(); ++ii) {
        if (m_replyData.at(ii) == '\n' && (!ii || m_replyData.at(ii - 1) != '\r')) {
            m_replyData.insert(ii, '\r');
            ++ii;
        }
    }
    m_replyData.append(m_bodyData);

    return true;
}

bool TestHTTPServer::hasFailed() const
{
    return m_state == Failed;
}

void TestHTTPServer::newConnection()
{
    QTcpSocket *socket = m_server.nextPendingConnection();
    if (!socket)
        return;

    if (!m_directories.isEmpty())
        m_dataCache.insert(socket, QByteArray());

    QObject::connect(socket, &QAbstractSocket::disconnected, this, &TestHTTPServer::disconnected);
    QObject::connect(socket, &QIODevice::readyRead, this, &TestHTTPServer::readyRead);
}

void TestHTTPServer::disconnected()
{
    QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
    if (!socket)
        return;

    m_dataCache.remove(socket);
    for (int ii = 0; ii < m_toSend.count(); ++ii) {
        if (m_toSend.at(ii).first == socket) {
            m_toSend.removeAt(ii);
            --ii;
        }
    }
    socket->disconnect();
    socket->deleteLater();
}

void TestHTTPServer::readyRead()
{
    QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
    if (!socket || socket->state() == QTcpSocket::ClosingState)
        return;

    if (!m_directories.isEmpty()) {
        serveGET(socket, socket->readAll());
        return;
    }

    if (m_state == Failed || (m_waitData.body.isEmpty() && m_waitData.headers.count() == 0)) {
        qWarning() << "TestHTTPServer: Unexpected data" << socket->readAll();
        return;
    }

    if (m_state == AwaitingHeader) {
        QByteArray line;
        while (!(line = socket->readLine()).isEmpty()) {
            line.replace('\r', "");
            if (line.at(0) == '\n') {
                m_state = AwaitingData;
                m_data += socket->readAll();
                break;
            } else {
                if (!m_waitData.headers.contains(line)) {
                    qWarning() << "TestHTTPServer: Unexpected header:" << line
                        << "\nExpected headers: " << m_waitData.headers;
                    m_state = Failed;
                    socket->disconnectFromHost();
                    return;
                }
            }
        }
    }  else {
        m_data += socket->readAll();
    }

    if (!m_data.isEmpty() || m_waitData.body.isEmpty()) {
        if (m_waitData.body != m_data) {
            qWarning() << "TestHTTPServer: Unexpected data" << m_data << "\nExpected: " << m_waitData.body;
            m_state = Failed;
        } else {
            socket->write(m_replyData);
        }
        socket->disconnectFromHost();
    }
}

bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileNameIn)
{
    const QString fileName = QLatin1String(fileNameIn);
    if (m_redirects.contains(fileName)) {
        const QByteArray response
            = "HTTP/1.1 302 Found\r\nContent-length: 0\r\nContent-type: text/html; charset=UTF-8\r\nLocation: "
              + m_redirects.value(fileName).toUtf8() + "\r\n\r\n";
        socket->write(response);
        return true;
    }

    for (int ii = 0; ii < m_directories.count(); ++ii) {
        const QString &dir = m_directories.at(ii).first;
        const Mode mode = m_directories.at(ii).second;

        QString dirFile = dir + QLatin1Char('/') + fileName;

        if (!QFile::exists(dirFile)) {
            const QHash<QString, QString>::const_iterator it = m_aliases.constFind(fileName);
            if (it != m_aliases.constEnd())
                dirFile = dir + QLatin1Char('/') + it.value();
        }

        QFile file(dirFile);
        if (file.open(QIODevice::ReadOnly)) {

            if (mode == Disconnect)
                return true;

            QByteArray data = file.readAll();
            if (m_contentSubstitutedFileNames.contains(QLatin1Char('/') + fileName))
                data.replace(QByteArrayLiteral("{{ServerBaseUrl}}"), baseUrl().toString().toUtf8());

            QByteArray response
                = "HTTP/1.0 200 OK\r\nContent-type: text/html; charset=UTF-8\r\nContent-length: ";
            response += QByteArray::number(data.count());
            response += "\r\n\r\n";
            response += data;

            if (mode == Delay) {
                m_toSend.append(qMakePair(socket, response));
                QTimer::singleShot(500, this, &TestHTTPServer::sendOne);
                return false;
            } else {
                socket->write(response);
                return true;
            }
        }
    }

    socket->write("HTTP/1.0 404 Not found\r\nContent-type: text/html; charset=UTF-8\r\n\r\n");

    return true;
}

void TestHTTPServer::sendDelayedItem()
{
    sendOne();
}

void TestHTTPServer::sendOne()
{
    if (!m_toSend.isEmpty()) {
        m_toSend.first().first->write(m_toSend.first().second);
        m_toSend.first().first->close();
        m_toSend.removeFirst();
    }
}

void TestHTTPServer::serveGET(QTcpSocket *socket, const QByteArray &data)
{
    const QHash<QTcpSocket *, QByteArray>::iterator it = m_dataCache.find(socket);
    if (it == m_dataCache.end())
        return;

    QByteArray &total = it.value();
    total.append(data);

    if (total.contains("\n\r\n")) {
        bool close = true;
        if (total.startsWith("GET /")) {
            const int space = total.indexOf(' ', 4);
            if (space != -1)
                close = reply(socket, total.mid(5, space - 5));
        }
        m_dataCache.erase(it);
        if (close)
            socket->disconnectFromHost();
    }
}

ThreadedTestHTTPServer::ThreadedTestHTTPServer(const QString &dir, TestHTTPServer::Mode mode) :
    m_port(0)
{
    m_dirs[dir] = mode;
    start();
}

ThreadedTestHTTPServer::ThreadedTestHTTPServer(const QHash<QString, TestHTTPServer::Mode> &dirs) :
    m_dirs(dirs), m_port(0)
{
    start();
}

ThreadedTestHTTPServer::~ThreadedTestHTTPServer()
{
    quit();
    wait();
}

QUrl ThreadedTestHTTPServer::baseUrl() const
{
    return localHostUrl(m_port);
}

QUrl ThreadedTestHTTPServer::url(const QString &documentPath) const
{
    return baseUrl().resolved(documentPath);
}

QString ThreadedTestHTTPServer::urlString(const QString &documentPath) const
{
    return url(documentPath).toString();
}

void ThreadedTestHTTPServer::run()
{
    TestHTTPServer server;
    {
        QMutexLocker locker(&m_mutex);
        QVERIFY2(server.listen(), qPrintable(server.errorString()));
        m_port = server.port();
        for (QHash<QString, TestHTTPServer::Mode>::ConstIterator i = m_dirs.constBegin();
             i != m_dirs.constEnd(); ++i) {
            server.serveDirectory(i.key(), i.value());
        }
        m_condition.wakeAll();
    }
    exec();
}

void ThreadedTestHTTPServer::start()
{
    QMutexLocker locker(&m_mutex);
    QThread::start();
    m_condition.wait(&m_mutex);
}
