/*
// 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.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/local/stream_protocol.hpp>
#include <boost/asio/write.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 <websocket.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.getIoContext(), stream_protocol::endpoint(socketId)),
        connection(connIn)
    {}

    NbdProxyServer(const NbdProxyServer&) = delete;
    NbdProxyServer(NbdProxyServer&&) = delete;
    NbdProxyServer& operator=(const NbdProxyServer&) = delete;
    NbdProxyServer& operator=(NbdProxyServer&&) = delete;

    ~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;

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

            auto getUserInfoHandler = [&conn, asyncResp](
                                          const boost::system::error_code ec,
                                          const dbus::utilities::
                                              DBusPropertiesMap& 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, interfaces] : objects)
                    {
                        for (const auto& [interface, properties] : interfaces)
                        {
                            if (interface !=
                                "xyz.openbmc_project.VirtualMedia.MountPoint")
                            {
                                continue;
                            }

                            for (const auto& [name, value] : properties)
                            {
                                if (name == "EndpointId")
                                {
                                    endpointValue =
                                        std::get_if<std::string>(&value);

                                    if (endpointValue == nullptr)
                                    {
                                        BMCWEB_LOG_ERROR
                                            << "EndpointId property value is null";
                                    }
                                }
                                if (name == "Socket")
                                {
                                    socketValue =
                                        std::get_if<std::string>(&value);
                                    if (socketValue == nullptr)
                                    {
                                        BMCWEB_LOG_ERROR
                                            << "Socket property value is null";
                                    }
                                }
                            }
                        }

                        if ((endpointValue != nullptr) &&
                            (socketValue != nullptr) &&
                            *endpointValue == conn.req.target())
                        {
                            endpointObjectPath = &objectPath.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, *socketValue, *endpointValue,
                        *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
