/*
// 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 <experimental/filesystem>
#include <privileges.hpp>
#include <variant>
#include <webserver_common.hpp>

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";
        close();
    }

    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 = [](const boost::system::error_code ec,
                               const bool status) {
            if (ec)
            {
                BMCWEB_LOG_ERROR << "DBus error: cannot call mount method = "
                                 << ec.message();
                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(CrowApp& 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{std::move(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...";
                    asyncResp->res.result(
                        boost::beast::http::status::internal_server_error);
                    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";
                    asyncResp->res.result(
                        boost::beast::http::status::unauthorized);
                    return;
                }

                for (const auto session : sessions)
                {
                    if (session.second->getEndpointId() == conn.req.target())
                    {
                        BMCWEB_LOG_ERROR
                            << "Cannot open new connection - socket is in use";
                        asyncResp->res.result(
                            boost::beast::http::status::bad_request);
                        return;
                    }
                }

                auto openHandler = [asyncResp,
                                    &conn](const boost::system::error_code ec,
                                           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();
                        asyncResp->res.result(
                            boost::beast::http::status::internal_server_error);
                        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 (endpointObjectPath == nullptr)
                    {
                        BMCWEB_LOG_ERROR << "Cannot find requested EndpointId";
                        asyncResp->res.result(
                            boost::beast::http::status::not_found);
                        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();

                    asyncResp->res.result(boost::beast::http::status::ok);
                };
                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;
                }
                session->second->close();
                // Remove reference to session in global map
                sessions.erase(session);
            })
        .onmessage([](crow::websocket::Connection& conn,
                      const std::string& data, bool isBinary) {
            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;
                }
            }
            conn.close();
        });
}
} // namespace nbd_proxy
} // namespace crow
