/*
// Copyright (c) 2019 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#pragma once
#include <app.h>
#include <websocket.h>

#include <boost/asio.hpp>
#include <boost/beast/core/buffers_to_string.hpp>
#include <boost/beast/core/multi_buffer.hpp>
#include <boost/container/flat_map.hpp>
#include <dbus_utility.hpp>
#include <privileges.hpp>

#include <variant>

namespace crow
{

namespace nbd_proxy
{

using boost::asio::local::stream_protocol;

static constexpr auto nbdBufferSize = 131088;
static const char* requiredPrivilegeString = "ConfigureManager";

struct NbdProxyServer : std::enable_shared_from_this<NbdProxyServer>
{
    NbdProxyServer(crow::websocket::Connection& connIn,
                   const std::string& socketIdIn,
                   const std::string& endpointIdIn, const std::string& pathIn) :
        socketId(socketIdIn),
        endpointId(endpointIdIn), path(pathIn),
        acceptor(connIn.get_io_context(), stream_protocol::endpoint(socketId)),
        connection(connIn)
    {}

    ~NbdProxyServer()
    {
        BMCWEB_LOG_DEBUG << "NbdProxyServer destructor";
    }

    std::string getEndpointId() const
    {
        return endpointId;
    }

    void run()
    {
        acceptor.async_accept(
            [this, self(shared_from_this())](boost::system::error_code ec,
                                             stream_protocol::socket socket) {
                if (ec)
                {
                    BMCWEB_LOG_ERROR << "UNIX socket: async_accept error = "
                                     << ec.message();
                    return;
                }
                if (peerSocket)
                {
                    // Something is wrong - socket shouldn't be acquired at this
                    // point
                    BMCWEB_LOG_ERROR
                        << "Failed to open connection - socket already used";
                    return;
                }

                BMCWEB_LOG_DEBUG << "Connection opened";
                peerSocket = std::move(socket);
                doRead();

                // Trigger Write if any data was sent from server
                // Initially this is negotiation chunk
                doWrite();
            });

        auto mountHandler = [this, self(shared_from_this())](
                                const boost::system::error_code ec,
                                const bool) {
            if (ec)
            {
                BMCWEB_LOG_ERROR << "DBus error: cannot call mount method = "
                                 << ec.message();
                connection.close("Failed to mount media");
                return;
            }
        };

        crow::connections::systemBus->async_method_call(
            std::move(mountHandler), "xyz.openbmc_project.VirtualMedia", path,
            "xyz.openbmc_project.VirtualMedia.Proxy", "Mount");
    }

    void send(const std::string_view data)
    {
        boost::asio::buffer_copy(ws2uxBuf.prepare(data.size()),
                                 boost::asio::buffer(data));
        ws2uxBuf.commit(data.size());
        doWrite();
    }

    void close()
    {
        acceptor.close();
        if (peerSocket)
        {
            BMCWEB_LOG_DEBUG << "peerSocket->close()";
            peerSocket->close();
            peerSocket.reset();
            BMCWEB_LOG_DEBUG << "std::remove(" << socketId << ")";
            std::remove(socketId.c_str());
        }
        // The reference to session should exists until unmount is
        // called
        auto unmountHandler = [](const boost::system::error_code ec) {
            if (ec)
            {
                BMCWEB_LOG_ERROR << "DBus error: " << ec
                                 << ", cannot call unmount method";
                return;
            }
        };

        crow::connections::systemBus->async_method_call(
            std::move(unmountHandler), "xyz.openbmc_project.VirtualMedia", path,
            "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
    }

  private:
    void doRead()
    {
        if (!peerSocket)
        {
            BMCWEB_LOG_DEBUG << "UNIX socket isn't created yet";
            // Skip if UNIX socket is not created yet.
            return;
        }

        // Trigger async read
        peerSocket->async_read_some(
            ux2wsBuf.prepare(nbdBufferSize),
            [this, self(shared_from_this())](boost::system::error_code ec,
                                             std::size_t bytesRead) {
                if (ec)
                {
                    BMCWEB_LOG_ERROR << "UNIX socket: async_read_some error = "
                                     << ec.message();
                    // UNIX socket has been closed by peer, best we can do is to
                    // break all connections
                    close();
                    return;
                }

                // Fetch data from UNIX socket

                ux2wsBuf.commit(bytesRead);

                // Paste it to WebSocket as binary
                connection.sendBinary(
                    boost::beast::buffers_to_string(ux2wsBuf.data()));
                ux2wsBuf.consume(bytesRead);

                // Allow further reads
                doRead();
            });
    }

    void doWrite()
    {
        if (!peerSocket)
        {
            BMCWEB_LOG_DEBUG << "UNIX socket isn't created yet";
            // Skip if UNIX socket is not created yet. Collect data, and wait
            // for nbd-client connection
            return;
        }

        if (uxWriteInProgress)
        {
            BMCWEB_LOG_ERROR << "Write in progress";
            return;
        }

        if (ws2uxBuf.size() == 0)
        {
            BMCWEB_LOG_ERROR << "No data to write to UNIX socket";
            return;
        }

        uxWriteInProgress = true;
        boost::asio::async_write(
            *peerSocket, ws2uxBuf.data(),
            [this, self(shared_from_this())](boost::system::error_code ec,
                                             std::size_t bytesWritten) {
                ws2uxBuf.consume(bytesWritten);
                uxWriteInProgress = false;
                if (ec)
                {
                    BMCWEB_LOG_ERROR << "UNIX: async_write error = "
                                     << ec.message();
                    return;
                }
                // Retrigger doWrite if there is something in buffer
                if (ws2uxBuf.size() > 0)
                {
                    doWrite();
                }
            });
    }

    // Keeps UNIX socket endpoint file path
    const std::string socketId;
    const std::string endpointId;
    const std::string path;

    bool uxWriteInProgress = false;

    // UNIX => WebSocket buffer
    boost::beast::multi_buffer ux2wsBuf;

    // WebSocket <= UNIX buffer
    boost::beast::multi_buffer ws2uxBuf;

    // Default acceptor for UNIX socket
    stream_protocol::acceptor acceptor;

    // The socket used to communicate with the client.
    std::optional<stream_protocol::socket> peerSocket;

    crow::websocket::Connection& connection;
};

static boost::container::flat_map<crow::websocket::Connection*,
                                  std::shared_ptr<NbdProxyServer>>
    sessions;

void requestRoutes(App& app)
{
    BMCWEB_ROUTE(app, "/nbd/<str>")
        .websocket()
        .onopen([](crow::websocket::Connection& conn,
                   std::shared_ptr<bmcweb::AsyncResp> asyncResp) {
            BMCWEB_LOG_DEBUG << "nbd-proxy.onopen(" << &conn << ")";

            auto getUserInfoHandler =
                [&conn, asyncResp](
                    const boost::system::error_code ec,
                    boost::container::flat_map<
                        std::string, std::variant<bool, std::string,
                                                  std::vector<std::string>>>
                        userInfo) {
                    if (ec)
                    {
                        BMCWEB_LOG_ERROR << "GetUserInfo failed...";
                        conn.close("Failed to get user information");
                        return;
                    }

                    const std::string* userRolePtr = nullptr;
                    auto userInfoIter = userInfo.find("UserPrivilege");
                    if (userInfoIter != userInfo.end())
                    {
                        userRolePtr =
                            std::get_if<std::string>(&userInfoIter->second);
                    }

                    std::string userRole{};
                    if (userRolePtr != nullptr)
                    {
                        userRole = *userRolePtr;
                        BMCWEB_LOG_DEBUG << "userName = " << conn.getUserName()
                                         << " userRole = " << *userRolePtr;
                    }

                    // Get the user privileges from the role
                    ::redfish::Privileges userPrivileges =
                        ::redfish::getUserPrivileges(userRole);

                    const ::redfish::Privileges requiredPrivileges{
                        requiredPrivilegeString};

                    if (!userPrivileges.isSupersetOf(requiredPrivileges))
                    {
                        BMCWEB_LOG_DEBUG
                            << "User " << conn.getUserName()
                            << " not authorized for nbd connection";
                        conn.close("Unathourized access");
                        return;
                    }

                    auto openHandler = [&conn, asyncResp](
                                           const boost::system::error_code ec,
                                           const dbus::utility::
                                               ManagedObjectType& objects) {
                        const std::string* socketValue = nullptr;
                        const std::string* endpointValue = nullptr;
                        const std::string* endpointObjectPath = nullptr;

                        if (ec)
                        {
                            BMCWEB_LOG_ERROR << "DBus error: " << ec.message();
                            conn.close("Failed to create mount point");
                            return;
                        }

                        for (const auto& objectPath : objects)
                        {
                            const auto interfaceMap = objectPath.second.find(
                                "xyz.openbmc_project.VirtualMedia.MountPoint");

                            if (interfaceMap == objectPath.second.end())
                            {
                                BMCWEB_LOG_DEBUG
                                    << "Cannot find MountPoint object";
                                continue;
                            }

                            const auto endpoint =
                                interfaceMap->second.find("EndpointId");
                            if (endpoint == interfaceMap->second.end())
                            {
                                BMCWEB_LOG_DEBUG
                                    << "Cannot find EndpointId property";
                                continue;
                            }

                            endpointValue =
                                std::get_if<std::string>(&endpoint->second);

                            if (endpointValue == nullptr)
                            {
                                BMCWEB_LOG_ERROR
                                    << "EndpointId property value is null";
                                continue;
                            }

                            if (*endpointValue == conn.req.target())
                            {
                                const auto socket =
                                    interfaceMap->second.find("Socket");
                                if (socket == interfaceMap->second.end())
                                {
                                    BMCWEB_LOG_DEBUG
                                        << "Cannot find Socket property";
                                    continue;
                                }

                                socketValue =
                                    std::get_if<std::string>(&socket->second);
                                if (socketValue == nullptr)
                                {
                                    BMCWEB_LOG_ERROR
                                        << "Socket property value is null";
                                    continue;
                                }

                                endpointObjectPath = &objectPath.first.str;
                                break;
                            }
                        }

                        if (objects.empty() || endpointObjectPath == nullptr)
                        {
                            BMCWEB_LOG_ERROR
                                << "Cannot find requested EndpointId";
                            conn.close("Failed to match EndpointId");
                            return;
                        }

                        for (const auto& session : sessions)
                        {
                            if (session.second->getEndpointId() ==
                                conn.req.target())
                            {
                                BMCWEB_LOG_ERROR
                                    << "Cannot open new connection - socket is "
                                       "in use";
                                conn.close("Slot is in use");
                                return;
                            }
                        }

                        // If the socket file exists (i.e. after bmcweb crash),
                        // we cannot reuse it.
                        std::remove((*socketValue).c_str());

                        sessions[&conn] = std::make_shared<NbdProxyServer>(
                            conn, std::move(*socketValue),
                            std::move(*endpointValue),
                            std::move(*endpointObjectPath));

                        sessions[&conn]->run();
                    };
                    crow::connections::systemBus->async_method_call(
                        std::move(openHandler),
                        "xyz.openbmc_project.VirtualMedia",
                        "/xyz/openbmc_project/VirtualMedia",
                        "org.freedesktop.DBus.ObjectManager",
                        "GetManagedObjects");
                };

            crow::connections::systemBus->async_method_call(
                std::move(getUserInfoHandler),
                "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
                "xyz.openbmc_project.User.Manager", "GetUserInfo",
                conn.getUserName());
        })
        .onclose(
            [](crow::websocket::Connection& conn, const std::string& reason) {
                BMCWEB_LOG_DEBUG << "nbd-proxy.onclose(reason = '" << reason
                                 << "')";
                auto session = sessions.find(&conn);
                if (session == sessions.end())
                {
                    BMCWEB_LOG_DEBUG << "No session to close";
                    return;
                }
                // Remove reference to session in global map
                sessions.erase(session);
                session->second->close();
            })
        .onmessage([](crow::websocket::Connection& conn,
                      const std::string& data, bool) {
            BMCWEB_LOG_DEBUG << "nbd-proxy.onmessage(len = " << data.length()
                             << ")";
            // Acquire proxy from sessions
            auto session = sessions.find(&conn);
            if (session != sessions.end())
            {
                if (session->second)
                {
                    session->second->send(data);
                    return;
                }
            }
        });
}
} // namespace nbd_proxy
} // namespace crow
