// Copyright 2024 Google LLC
//
// 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.

#include "hoth.hpp"

#include <ipmid/api-types.hpp>
#include <ipmid/handler.hpp>
#include <stdplus/util/string.hpp>

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>

namespace ipmi_hoth
{

std::string_view HothBlobHandler::pathToHothId(std::string_view path)
{
    if (path.starts_with(hothPathPrefix) && path.ends_with(pathSuffix()))
    {
        auto id = path.substr(
            hothPathPrefix.size(),
            path.size() - pathSuffix().size() - hothPathPrefix.size());
        auto count = std::count(id.begin(), id.end(), '/');

        // There can only be prefix + pathSuffix or
        // prefix + id/pathSuffix.
        // prefix already has one `/`
        if (count == 1)
        {
            return id.substr(0, id.size() - 1);
        }
        else if (count > 1)
        {
            return "";
        }

        return id;
    }
    return "";
}

std::string HothBlobHandler::hothIdToPath(std::string_view hothId)
{
    if (hothId.empty())
    {
        return stdplus::util::strCat(hothPathPrefix, pathSuffix());
    }
    return stdplus::util::strCat(hothPathPrefix, hothId, "/", pathSuffix());
}

HothBlob* HothBlobHandler::getSession(uint16_t id)
{
    auto search = sessions.find(id);
    if (search == sessions.end())
    {
        return nullptr;
    }

    /* Not thread-safe, however, the blob handler deliberately assumes serial
     * execution. */
    return search->second.get();
}

std::optional<uint16_t> HothBlobHandler::getOnlySession(std::string_view hothId)
{
    /* This method is only valid if we only allow 1 session */
    if (maxSessions() != 1)
    {
        return std::nullopt;
    }

    for (auto& session : pathSessions[std::string(hothId)])
    {
        return session;
    }

    return std::nullopt;
}

bool HothBlobHandler::canHandleBlob(const std::string& path)
{
    if (path.starts_with(hothPathPrefix) && path.ends_with(pathSuffix()))
    {
        // There can only be hothPathPrefix + pathSuffix or
        // hothPathPrefix + id/pathSuffix
        // hothPathPrefix already has one `/`
        return std::count(path.begin() + hothPathPrefix.size(),
                          path.end() - pathSuffix().size(), '/') <= 1;
    }
    return false;
}

std::vector<std::string> HothBlobHandler::getBlobIds()
{
    std::vector<std::string> ret;
    for (const auto& obj : dbus().getHothdMapping())
    {
        std::string_view objView = obj.first;
        std::string_view objPrefix = "/xyz/openbmc_project/Control/Hoth";
        if (objView.substr(0, objPrefix.size()) != objPrefix)
        {
            continue;
        }
        objView.remove_prefix(objPrefix.size());
        if (objView.empty())
        {
            ret.push_back(hothIdToPath(""));
            continue;
        }
        if (objView[0] != '/')
        {
            continue;
        }
        objView.remove_prefix(1);
        auto sep = objView.find('/');
        if (sep != std::string_view::npos)
        {
            continue;
        }
        ret.push_back(hothIdToPath(objView));
    }
    return ret;
}

bool HothBlobHandler::deleteBlob(const std::string&)
{
    /* Hoth blob handler does not support a blob delete. */
    return false;
}

bool HothBlobHandler::open(uint16_t session, uint16_t flags,
                           const std::string& path)
{
    /* We require both flags set. */
    if ((flags & requiredFlags()) != requiredFlags())
    {
        /* Both flags not set. */
        return false;
    }

    auto findSess = sessions.find(session);
    if (findSess != sessions.end())
    {
        /* This session is already active. */
        return false;
    }

    auto hothId = std::string(pathToHothId(path));
    auto pathSession = pathSessions.find(hothId);
    if (pathSession != pathSessions.end() &&
        pathSession->second.size() >= maxSessions())
    {
        return false;
    }

    // Prevent host from adding lots of bad entries to the table by verifying
    // the hoth exists.
    if (pathSession == pathSessions.end() && !dbus().pingHothd(hothId))
    {
        return false;
    }

    pathSessions[hothId].emplace(session);
    sessions.emplace(session,
                     std::make_unique<HothBlob>(session, std::move(hothId),
                                                flags, maxBufferSize()));
    return true;
}

std::vector<uint8_t> HothBlobHandler::read(uint16_t session, uint32_t offset,
                                           uint32_t requestedSize)
{
    HothBlob* sess = getSession(session);
    if (!sess || !(sess->state & blobs::StateFlags::open_read) ||
        offset > sess->buffer.size())
    {
        throw ipmi::HandlerCompletion(ipmi::ccUnspecifiedError);
    }

    if (sess->buffer.size() > offset)
    {
        std::vector<uint8_t> ret(
            std::min<size_t>(requestedSize, sess->buffer.size() - offset));
        std::memcpy(ret.data(), sess->buffer.data() + offset, ret.size());
        return ret;
    }
    return {};
}

bool HothBlobHandler::write(uint16_t session, uint32_t offset,
                            const std::vector<uint8_t>& data)
{
    uint32_t newBufferSize = data.size() + offset;
    HothBlob* sess = getSession(session);
    if (!sess || !(sess->state & blobs::StateFlags::open_write) ||
        newBufferSize > maxBufferSize())
    {
        return false;
    }

    /* Resize the buffer if what we're writing will go over the size */
    if (newBufferSize > sess->buffer.size())
    {
        sess->buffer.resize(newBufferSize);
        sess->state &= ~blobs::StateFlags::committed;
    }

    /* Clear the comitted bit if our data isn't identical to existing data */
    if (std::memcmp(sess->buffer.data() + offset, data.data(), data.size()))
    {
        sess->state &= ~blobs::StateFlags::committed;
    }
    if (!data.empty())
    {
        std::memcpy(sess->buffer.data() + offset, data.data(), data.size());
    }
    return true;
}

bool HothBlobHandler::writeMeta(uint16_t, uint32_t, const std::vector<uint8_t>&)
{
    /* Hoth blob handler does not support meta write. */
    return false;
}

bool HothBlobHandler::close(uint16_t session)
{
    auto session_it = sessions.find(session);
    if (session_it == sessions.end())
    {
        return false;
    }

    auto path_it = pathSessions.find(session_it->second->hothId);
    path_it->second.erase(session);
    if (path_it->second.empty())
    {
        pathSessions.erase(path_it);
    }

    sessions.erase(session_it);
    return true;
}

bool HothBlobHandler::expire(uint16_t session)
{
    return close(session);
}

} // namespace ipmi_hoth
