#include "version_handler.hpp"

#include <utility>
#include <vector>

namespace ipmi_flash
{

VersionBlobHandler::VersionBlobHandler(
    std::vector<HandlerConfig<ActionPack>>&& configs)
{
    for (auto& config : configs)
    {
        auto info = std::make_unique<BlobInfo>();
        info->blobId = std::move(config.blobId);
        info->actions = std::move(config.actions);
        info->handler = std::move(config.handler);
        info->actions->onOpen->setCallback(
            [infoP = info.get()](TriggerableActionInterface& tai) {
                auto data =
                    std::make_shared<std::optional<std::vector<uint8_t>>>();
                do
                {
                    if (tai.status() != ActionStatus::success)
                    {
                        fprintf(stderr, "Version file unit failed for %s\n",
                                infoP->blobId.c_str());
                        continue;
                    }
                    if (!infoP->handler->open("", std::ios::in))
                    {
                        fprintf(stderr, "Opening version file failed for %s\n",
                                infoP->blobId.c_str());
                        continue;
                    }
                    auto d = infoP->handler->read(
                        0, std::numeric_limits<uint32_t>::max());
                    infoP->handler->close();
                    if (!d)
                    {
                        fprintf(stderr, "Reading version file failed for %s\n",
                                infoP->blobId.c_str());
                        continue;
                    }
                    *data = std::move(d);
                } while (false);
                for (auto sessionP : infoP->sessionsToUpdate)
                {
                    sessionP->data = data;
                }
                infoP->sessionsToUpdate.clear();
            });
        if (!blobInfoMap.try_emplace(info->blobId, std::move(info)).second)
        {
            fprintf(stderr, "Ignoring duplicate config for %s\n",
                    info->blobId.c_str());
        }
    }
}

bool VersionBlobHandler::canHandleBlob(const std::string& path)
{
    return blobInfoMap.find(path) != blobInfoMap.end();
}

std::vector<std::string> VersionBlobHandler::getBlobIds()
{
    std::vector<std::string> ret;
    for (const auto& [key, _] : blobInfoMap)
    {
        ret.emplace_back(key);
    }
    return ret;
}

/**
 * deleteBlob - does nothing, always fails
 */
bool VersionBlobHandler::deleteBlob(const std::string& path)
{
    return false;
}

bool VersionBlobHandler::stat(const std::string& path, blobs::BlobMeta* meta)
{
    return false;
}

bool VersionBlobHandler::open(uint16_t session, uint16_t flags,
                              const std::string& path)
{
    /* only reads are supported, check if blob is handled and make sure
     * the blob isn't already opened
     */
    if (flags != blobs::read)
    {
        fprintf(stderr, "open %s fail: unsupported flags(0x%04X.)\n",
                path.c_str(), flags);
        return false;
    }

    auto info = std::make_unique<SessionInfo>();
    info->blob = blobInfoMap.at(path).get();
    info->blob->sessionsToUpdate.emplace(info.get());
    if (info->blob->sessionsToUpdate.size() == 1 &&
        !info->blob->actions->onOpen->trigger())
    {
        fprintf(stderr, "open %s fail: onOpen trigger failed\n", path.c_str());
        info->blob->sessionsToUpdate.erase(info.get());
        return false;
    }

    sessionInfoMap[session] = std::move(info);
    return true;
}

std::vector<uint8_t> VersionBlobHandler::read(uint16_t session, uint32_t offset,
                                              uint32_t requestedSize)
{
    auto& data = sessionInfoMap.at(session)->data;
    if (data == nullptr || !*data)
    {
        throw std::runtime_error("Version data not ready for read");
    }
    if ((*data)->size() < offset)
    {
        return {};
    }
    std::vector<uint8_t> ret(
        std::min<size_t>(requestedSize, (*data)->size() - offset));
    std::memcpy(&ret[0], &(**data)[offset], ret.size());
    return ret;
}

bool VersionBlobHandler::close(uint16_t session)
{
    auto it = sessionInfoMap.find(session);
    if (it == sessionInfoMap.end())
    {
        return false;
    }
    auto& info = *it->second;
    info.blob->sessionsToUpdate.erase(&info);
    if (info.blob->sessionsToUpdate.empty())
    {
        info.blob->actions->onOpen->abort();
    }
    sessionInfoMap.erase(it);
    return true;
}

bool VersionBlobHandler::stat(uint16_t session, blobs::BlobMeta* meta)
{
    const auto& data = sessionInfoMap.at(session)->data;
    if (data == nullptr)
    {
        meta->blobState = blobs::StateFlags::committing;
        meta->size = 0;
    }
    else if (!*data)
    {
        meta->blobState = blobs::StateFlags::commit_error;
        meta->size = 0;
    }
    else
    {
        meta->blobState =
            blobs::StateFlags::committed | blobs::StateFlags::open_read;
        meta->size = (*data)->size();
    }
    return true;
}

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

} // namespace ipmi_flash
