#include "example/example.hpp"

#include <algorithm>
#include <blobs-ipmid/manager.hpp>
#include <cstring>
#include <memory>
#include <phosphor-logging/log.hpp>
#include <string>
#include <vector>

namespace blobs
{

using namespace phosphor::logging;

constexpr char ExampleBlobHandler::supportedPath[];

ExampleBlob* ExampleBlobHandler::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;
}

bool ExampleBlobHandler::canHandleBlob(const std::string& path)
{
    return (path == supportedPath);
}

std::vector<std::string> ExampleBlobHandler::getBlobIds()
{
    return {supportedPath};
}

bool ExampleBlobHandler::deleteBlob(const std::string& path)
{
    return false;
}

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

bool ExampleBlobHandler::open(uint16_t session, uint16_t flags,
                              const std::string& path)
{
    if (!canHandleBlob(path))
    {
        return false;
    }

    auto findSess = sessions.find(session);
    if (findSess != sessions.end())
    {
        /* This session is already active. */
        return false;
    }
    sessions[session] = ExampleBlob(session, flags);
    return true;
}

std::vector<uint8_t> ExampleBlobHandler::read(uint16_t session, uint32_t offset,
                                              uint32_t requestedSize)
{
    ExampleBlob* sess = getSession(session);
    if (!sess)
    {
        return std::vector<uint8_t>();
    }

    /* Is the offset beyond the array? */
    if (offset >= sizeof(sess->buffer))
    {
        return std::vector<uint8_t>();
    }

    /* Determine how many bytes we can read from the offset.
     * In this case, if they read beyond "size" we allow it.
     */
    uint32_t remain = sizeof(sess->buffer) - offset;
    uint32_t numBytes = std::min(remain, requestedSize);
    /* Copy the bytes! */
    std::vector<uint8_t> result(numBytes);
    std::memcpy(result.data(), &sess->buffer[offset], numBytes);
    return result;
}

bool ExampleBlobHandler::write(uint16_t session, uint32_t offset,
                               const std::vector<uint8_t>& data)
{
    ExampleBlob* sess = getSession(session);
    if (!sess)
    {
        return false;
    }
    /* Is the offset beyond the array? */
    if (offset >= sizeof(sess->buffer))
    {
        return false;
    }
    /* Determine whether all their bytes will fit. */
    uint32_t remain = sizeof(sess->buffer) - offset;
    if (data.size() > remain)
    {
        return false;
    }
    sess->length =
        std::max(offset + data.size(),
                 static_cast<std::vector<uint8_t>::size_type>(sess->length));
    std::memcpy(&sess->buffer[offset], data.data(), data.size());
    return true;
}

bool ExampleBlobHandler::writeMeta(uint16_t session, uint32_t offset,
                                   const std::vector<uint8_t>& data)
{
    /* Not supported. */
    return false;
}

bool ExampleBlobHandler::commit(uint16_t session,
                                const std::vector<uint8_t>& data)
{
    ExampleBlob* sess = getSession(session);
    if (!sess)
    {
        return false;
    }

    /* Do something with the staged data!. */

    return false;
}

bool ExampleBlobHandler::close(uint16_t session)
{
    ExampleBlob* sess = getSession(session);
    if (!sess)
    {
        return false;
    }

    sessions.erase(session);
    return true;
}

bool ExampleBlobHandler::stat(uint16_t session, struct BlobMeta* meta)
{
    ExampleBlob* sess = getSession(session);
    if (!sess)
    {
        return false;
    }
    if (!meta)
    {
        return false;
    }
    meta->size = sess->length;
    meta->blobState = sess->state;
    return true;
}

bool ExampleBlobHandler::expire(uint16_t session)
{
    ExampleBlob* sess = getSession(session);
    if (!sess)
    {
        return false;
    }
    /* TODO: implement session expiration behavior. */
    return false;
}

void setupExampleHandler() __attribute__((constructor));

void setupExampleHandler()
{
    // You don't need to do anything in the constructor.
}

} // namespace blobs

/**
 * This method is required by the blob manager.
 *
 * It is called to grab a handler for registering the blob handler instance.
 */
std::unique_ptr<blobs::GenericBlobInterface> createHandler()
{
    return std::make_unique<blobs::ExampleBlobHandler>();
}
