/*
 * Copyright (C) 2017 Igalia S.L.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "SessionHost.h"

#include "Logging.h"
#include <wtf/NeverDestroyed.h>
#include <wtf/Observer.h>
#include <wtf/WeakHashSet.h>
#include <wtf/text/StringBuilder.h>

namespace WebDriver {

#if ENABLE(WEBDRIVER_BIDI)
static WeakHashSet<SessionHost::BrowserTerminatedObserver>& browserTerminatedObservers()
{
    static NeverDestroyed<WeakHashSet<SessionHost::BrowserTerminatedObserver>> observers;
    return observers;
}
#endif

void SessionHost::inspectorDisconnected()
{
    Ref<SessionHost> protectedThis(*this);

    auto pendingRequestCount = m_commandRequests.size();
    if (pendingRequestCount)
        RELEASE_LOG_INFO(SessionHost, "Inspector disconnected; failing %u pending command(s)", pendingRequestCount);
    else
        RELEASE_LOG_INFO(SessionHost, "Inspector disconnected; no commands remaining.");

    // Browser closed or crashed, finish all pending commands with error.
    RefPtr<JSON::Object> errorResponse = JSON::Object::create();
    errorResponse->setString("message"_s, "Session terminated without a reply"_s);
    for (auto messageID : copyToVector(m_commandRequests.keys())) {
        auto responseHandler = m_commandRequests.take(messageID);
        responseHandler({ errorResponse , true });
    }

#if ENABLE(WEBDRIVER_BIDI)
    for (auto& observer : browserTerminatedObservers())
        observer(m_sessionID);
#endif
}

long SessionHost::sendCommandToBackend(const String& command, RefPtr<JSON::Object>&& parameters, Function<void (CommandResponse&&)>&& responseHandler)
{
    if (!isConnected()) {
        responseHandler({ nullptr, true });
        return 0;
    }

    static long lastSequenceID = 0;
    long sequenceID = ++lastSequenceID;
    m_commandRequests.add(sequenceID, WTF::move(responseHandler));
    StringBuilder messageBuilder;
    messageBuilder.append("{\"id\":"_s, sequenceID, ",\"method\":\"Automation."_s, command, '"');
    if (parameters)
        messageBuilder.append(",\"params\":"_s, parameters->toJSONString());
    messageBuilder.append('}');
    RELEASE_LOG_INFO(SessionHost, "    SEND inspector #%04ld: Automation.%s (%u bytes)", sequenceID, command.utf8().data(), messageBuilder.length());
    sendMessageToBackend(messageBuilder.toString());

    return sequenceID;
}

void SessionHost::dispatchMessage(const String& message)
{
    LOG(SessionHost, "SessionHost::dispatchMessage: %s", message.utf8().data());
    auto messageValue = JSON::Value::parseJSON(message);
    if (!messageValue)
        return;

    auto messageObject = messageValue->asObject();
    if (!messageObject)
        return;

    auto sequenceID = messageObject->getInteger("id"_s);
    if (!sequenceID) {
        auto method = messageObject->getString("method"_s);
        if (method == "Automation.browsingContextCleared"_s)
            return;
#if ENABLE(WEBDRIVER_BIDI)
        if (method != "Automation.bidiMessageSent"_s)
            return;
        dispatchBidiMessage(WTF::move(messageObject));
#else
        RELEASE_LOG_ERROR(SessionHost, "Received from browser message without id: %s", message.utf8().data());
#endif
        return;
    }

    auto responseHandler = m_commandRequests.take(*sequenceID);
    ASSERT(responseHandler);

    CommandResponse response;
    if (auto errorObject = messageObject->getObject("error"_s)) {
        response.responseObject = WTF::move(errorObject);
        response.isError = true;
    } else if (auto resultObject = messageObject->getObject("result"_s)) {
        if (resultObject->size())
            response.responseObject = WTF::move(resultObject);
    }
    RELEASE_LOG_INFO(SessionHost, "    RECV inspector #%04d: %s", *sequenceID, response.isError ? "error" : "ok");

    responseHandler(WTF::move(response));
}

bool SessionHost::isRemoteBrowser() const
{
    return m_isRemoteBrowser;
}

#if ENABLE(WEBDRIVER_BIDI)
void SessionHost::addBrowserTerminatedObserver(const BrowserTerminatedObserver& observer)
{
    ASSERT(!browserTerminatedObservers().contains(observer));
    browserTerminatedObservers().add(observer);
}

void SessionHost::removeBrowserTerminatedObserver(const BrowserTerminatedObserver& observer)
{
    browserTerminatedObservers().remove(observer);
}

void SessionHost::dispatchBidiMessage(RefPtr<JSON::Object>&& event)
{
    LOG(WebDriverBiDi, "SessionHost::dispatchBidiMessage: %s", event->toJSONString().utf8().data());
    if (m_bidiHandler)
        m_bidiHandler->dispatchBidiMessage(WTF::move(event));
    else
        RELEASE_LOG(SessionHost, "No bidi message handler to dispatch message %s", event->toJSONString().utf8().data());
}
#endif

} // namespace WebDriver
