#include "version_handler.hpp"

#include <stdexcept>
#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);
        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)
{
    // TODO: stat should return the blob state and in the meta data information
    // on whether a read is successful should be contained
    // do things like determine if systemd target is triggered
    // then check if file can be opened for read
    return false; /* not yet implemented */
}

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& v = *blobInfoMap.at(path);
    if (v.blobState == blobs::StateFlags::open_read)
    {
        fprintf(stderr, "open %s fail: blob already opened for read\n",
                path.c_str());
        return false;
    }
    if (v.actions->onOpen->trigger() == false)
    {
        fprintf(stderr, "open %s fail: onOpen trigger failed\n", path.c_str());
        return false;
    }

    v.blobState = blobs::StateFlags::open_read;
    sessionToBlob[session] = &v;
    return true;
}

std::vector<uint8_t> VersionBlobHandler::read(uint16_t session, uint32_t offset,
                                              uint32_t requestedSize)
{
    BlobInfo* pack;
    try
    {
        pack = sessionToBlob.at(session);
    }
    catch (const std::out_of_range& e)
    {
        return {};
    }
    /* onOpen trigger must be successful, otherwise potential
     * for stale data to be read
     */
    if (pack->actions->onOpen->status() != ActionStatus::success)
    {
        fprintf(stderr, "read failed: onOpen trigger not successful\n");
        return {};
    }
    if (!pack->handler->open("don't care", std::ios::in))
    {
        fprintf(stderr, "read failed: file open unsuccessful blob=%s\n",
                pack->blobId.c_str());
        return {};
    }
    auto d = pack->handler->read(offset, requestedSize);
    if (!d)
    {
        fprintf(stderr, "read failed: unable to read file for blob %s\n",
                pack->blobId.c_str());
        pack->handler->close();
        return {};
    }
    pack->handler->close();
    return *d;
}

bool VersionBlobHandler::close(uint16_t session)
{
    try
    {
        auto& pack = *sessionToBlob.at(session);
        pack.actions->onOpen->abort();
        pack.blobState = static_cast<blobs::StateFlags>(0);
        sessionToBlob.erase(session);
        return true;
    }
    catch (const std::out_of_range& e)
    {
        return false;
    }
}

bool VersionBlobHandler::stat(uint16_t session, blobs::BlobMeta* meta)
{
    return false;
}

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

} // namespace ipmi_flash
