/*
 * Copyright (C) 2019 Sony Interactive Entertainment Inc.
 *
 * 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 <wtf/NeverDestroyed.h>
#include <wtf/UUID.h>
#include <wtf/text/MakeString.h>

#if PLATFORM(WIN)
#include <shlwapi.h>
#include <ws2tcpip.h>
#endif

namespace WebDriver {

SessionHost::~SessionHost()
{
#if PLATFORM(WIN)
    if (m_browserHandle) {
        ::TerminateProcess(m_browserHandle.get(), 0);
        m_browserHandle = { };
    }
#endif
}

HashMap<String, Inspector::RemoteInspectorConnectionClient::CallHandler>& SessionHost::dispatchMap()
{
    static NeverDestroyed<HashMap<String, CallHandler>> methods = HashMap<String, CallHandler>({
        {"SetTargetList"_s, static_cast<CallHandler>(&SessionHost::receivedSetTargetList)},
        {"SendMessageToFrontend"_s, static_cast<CallHandler>(&SessionHost::receivedSendMessageToFrontend)},
        {"StartAutomationSession_Return"_s, static_cast<CallHandler>(&SessionHost::receivedStartAutomationSessionReturn)},
    });

    return methods;
}

void SessionHost::sendWebInspectorEvent(const String& event)
{
    if (!m_clientID)
        return;

    send(m_clientID.value(), byteCast<uint8_t>(event.utf8().span()));
}

#if PLATFORM(WIN)
static std::optional<unsigned> getFreePort()
{
    // This function binds port 0 and immediately closes it,
    // and returns the port number actually bound as a free port.

    // FIXME:
    // There is no guarantee that the port number returned by this function will always be available.
    // Another application may use it immediately.

    auto sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET)
        return std::nullopt;

    sockaddr_in address = { };
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = htonl(INADDR_ANY);
    address.sin_port = htons(0);
    int ret = bind(sock, reinterpret_cast<struct sockaddr*>(&address), sizeof(address));
    if (ret == SOCKET_ERROR) {
        closesocket(sock);
        return std::nullopt;
    }

    address = { };
    socklen_t len = sizeof(address);
    ret = getsockname(sock, reinterpret_cast<struct sockaddr*>(&address), &len);
    if (ret == SOCKET_ERROR) {
        closesocket(sock);
        return std::nullopt;
    }

    auto freePort = ntohs(address.sin_port);
    ::closesocket(sock);
    return freePort;
}

static WTF::Win32Handle launchBrowser()
{
    WCHAR pathStr[MAX_PATH];
    if (!::GetModuleFileName(nullptr, pathStr, std::size(pathStr)))
        return { };

    // Launch MiniBrowser.exe in the same path as WebDriver.exe.
    // FIXME: It would be even better if the WebKit browsers elsewhere instead of MiniBrowser could be specified.
    ::PathRemoveFileSpec(pathStr);
    if (!::PathAppend(pathStr, L"MiniBrowser.exe"))
        return { };

    auto commandLine = makeString('"', String(pathStr), '"');

    STARTUPINFO startupInfo { };
    startupInfo.cb = sizeof(startupInfo);
    startupInfo.dwFlags = STARTF_USESHOWWINDOW;
    startupInfo.wShowWindow = SW_HIDE;
    PROCESS_INFORMATION processInformation { };
    if (::CreateProcess(0, commandLine.wideCharacters().mutableSpan().data(), 0, 0, true, 0, 0, 0, &startupInfo, &processInformation))
        return Win32Handle::adopt(processInformation.hProcess);

    return { };
}
#endif

void SessionHost::connectToBrowser(Function<void (std::optional<String> error)>&& completionHandler)
{
    if (m_clientID) {
        completionHandler(makeString("Already connected to the browser."_s));
        return;
    }

    String targetIp;
    uint16_t targetPort = 0;

    if (!m_targetIp.isEmpty() && m_targetPort) {
        targetIp = m_targetIp;
        targetPort = m_targetPort;
    } else if (m_capabilities.targetAddr && m_capabilities.targetPort) {
        targetIp = m_capabilities.targetAddr.value();
        targetPort = m_capabilities.targetPort.value();
    }

    if (targetIp.isEmpty() || !targetPort) {
#if !PLATFORM(WIN)
        completionHandler(makeString("Target IP/port is invalid, or not specified."_s));
        return;
#else
        // WebDriver will launch MiniBrowser for automation if both "-t" and "--target" options are not specified.
        auto freePort = getFreePort();
        if (!freePort) {
            completionHandler(makeString("Failed to launch MiniBrowser."_s));
            return;
        }

        targetIp = "127.0.0.1"_s;
        targetPort = *freePort;

        auto envVar = makeString(targetIp, ':', targetPort);
        ::SetEnvironmentVariable(L"WEBKIT_INSPECTOR_SERVER", envVar.wideCharacters().span().data());

        m_browserHandle = launchBrowser();
        if (!m_browserHandle) {
            completionHandler(makeString("Failed to launch MiniBrowser."_s));
            return;
        }
        m_isRemoteBrowser = false;
#endif
    } else
        m_isRemoteBrowser = true;

    m_clientID = connectInet(targetIp.utf8().data(), targetPort);
    if (!m_clientID)
        completionHandler(makeString(targetIp.utf8().span(), ':', targetPort, " is not reachable."_s));
    else
        completionHandler(std::nullopt);
}

bool SessionHost::isConnected() const
{
    return m_clientID.has_value();
}

void SessionHost::didClose(Inspector::RemoteInspectorSocketEndpoint&, Inspector::ConnectionID)
{
    inspectorDisconnected();

#if PLATFORM(WIN)
    if (m_browserHandle) {
        ::TerminateProcess(m_browserHandle.get(), 0);
        m_browserHandle = { };
    }
#endif

    m_clientID = std::nullopt;
}

std::optional<Vector<SessionHost::Target>> SessionHost::parseTargetList(const struct Event& event)
{
    auto result = parseTargetListJSON(*event.message);
    if (!result)
        return std::nullopt;

    Vector<SessionHost::Target> targetList;
    for (const auto& itemObject : *result) {
        SessionHost::Target target;
        String name;
        String type;
        auto targetId = itemObject->getInteger("targetID"_s);
        if (!targetId
            || !itemObject->getString("name"_s, name)
            || !itemObject->getString("type"_s, type)
            || type != "automation"_s)
            continue;

        target.id = *targetId;
        target.name = name.utf8();
        targetList.append(target);
    }
    return targetList;
}

void SessionHost::receivedSetTargetList(const struct Event& event)
{
    ASSERT(isMainThread());

    if (!event.connectionID || !event.message)
        return;

    auto targetList = parseTargetList(event);
    if (targetList)
        setTargetList(*event.connectionID, WTF::move(*targetList));
}

void SessionHost::receivedSendMessageToFrontend(const struct Event& event)
{
    ASSERT(isMainThread());

    if (!event.connectionID || !event.targetID || !event.message)
        return;

    ASSERT(*event.connectionID == m_connectionID && *event.targetID == m_target.id);
    dispatchMessage(event.message.value());
}

void SessionHost::receivedStartAutomationSessionReturn(const struct Event&)
{
    ASSERT(isMainThread());

    m_capabilities.browserName = String::fromUTF8("TODO/browserName");
    m_capabilities.browserVersion = String::fromUTF8("TODO/browserVersion");
}

void SessionHost::startAutomationSession(Function<void (bool, std::optional<String>)>&& completionHandler)
{
    ASSERT(!m_startSessionCompletionHandler);
    m_startSessionCompletionHandler = WTF::move(completionHandler);
    m_sessionID = createVersion4UUIDString();

    auto capabilitiesObject = JSON::Object::create();
    capabilitiesObject->setBoolean("acceptInsecureCerts"_s, m_capabilities.acceptInsecureCerts.value_or(false));

    auto messageObject = JSON::Object::create();
    messageObject->setString("sessionID"_s, m_sessionID);
    messageObject->setObject("capabilities"_s, capabilitiesObject);

    auto sendMessageEvent = JSON::Object::create();
    sendMessageEvent->setString("event"_s, "StartAutomationSession"_s);
    sendMessageEvent->setString("message"_s, messageObject->toJSONString());
    sendWebInspectorEvent(sendMessageEvent->toJSONString());
}

void SessionHost::setTargetList(uint64_t connectionID, Vector<Target>&& targetList)
{
    // The server notifies all its clients when connection is lost by sending an empty target list.
    // We only care about automation connection.
    if (m_connectionID && m_connectionID != connectionID)
        return;

    ASSERT(targetList.size() <= 1);
    if (targetList.isEmpty()) {
        // Disconnected from backend
        m_clientID = std::nullopt;
        inspectorDisconnected();
        if (m_startSessionCompletionHandler) {
            auto startSessionCompletionHandler = std::exchange(m_startSessionCompletionHandler, nullptr);
            startSessionCompletionHandler(true, "received empty target list"_s);
        }
        return;
    }

    m_target = targetList[0];
    if (m_connectionID) {
        ASSERT(m_connectionID == connectionID);
        return;
    }

    if (!m_startSessionCompletionHandler) {
        // Session creation was already rejected.
        return;
    }

    m_connectionID = connectionID;

    auto sendEvent = JSON::Object::create();
    sendEvent->setString("event"_s, "Setup"_s);
    sendEvent->setInteger("connectionID"_s, m_connectionID);
    sendEvent->setInteger("targetID"_s, m_target.id);
    sendWebInspectorEvent(sendEvent->toJSONString());

    auto startSessionCompletionHandler = std::exchange(m_startSessionCompletionHandler, nullptr);
    startSessionCompletionHandler(true, std::nullopt);
}

void SessionHost::sendMessageToBackend(const String& message)
{
    auto sendEvent = JSON::Object::create();
    sendEvent->setString("event"_s, "SendMessageToBackend"_s);
    sendEvent->setInteger("connectionID"_s, m_connectionID);
    sendEvent->setInteger("targetID"_s, m_target.id);
    sendEvent->setString("message"_s, message);
    sendWebInspectorEvent(sendEvent->toJSONString());
}

} // namespace WebDriver
