#include "binarystore.hpp"

#include "sys_file.hpp"

#include <sys/types.h>
#include <unistd.h>

#include <algorithm>
#include <blobs-ipmid/blobs.hpp>
#include <boost/endian/arithmetic.hpp>
#include <cstdint>
#include <ipmid/handler.hpp>
#include <memory>
#include <optional>
#include <phosphor-logging/elog.hpp>
#include <string>
#include <vector>

#include "binaryblob.pb.h"

using std::size_t;
using std::uint16_t;
using std::uint32_t;
using std::uint64_t;
using std::uint8_t;

namespace binstore
{

using namespace phosphor::logging;

std::unique_ptr<BinaryStoreInterface> BinaryStore::createFromConfig(
    const std::string& baseBlobId, std::unique_ptr<SysFile> file,
    std::optional<uint32_t> maxSize, std::optional<std::string> aliasBlobBaseId)
{
    if (baseBlobId.empty() || !file)
    {
        log<level::ERR>("Unable to create binarystore from invalid config",
                        entry("BASE_ID=%s", baseBlobId.c_str()));
        return nullptr;
    }

    auto store =
        std::make_unique<BinaryStore>(baseBlobId, std::move(file), maxSize);

    if (!store->loadSerializedData(aliasBlobBaseId))
    {
        return nullptr;
    }

    return store;
}

std::unique_ptr<BinaryStoreInterface>
    BinaryStore::createFromFile(std::unique_ptr<SysFile> file, bool readOnly,
                                std::optional<uint32_t> maxSize)
{
    if (!file)
    {
        log<level::ERR>("Unable to create binarystore from invalid file");
        return nullptr;
    }

    auto store =
        std::make_unique<BinaryStore>(std::move(file), readOnly, maxSize);

    if (!store->loadSerializedData())
    {
        return nullptr;
    }

    return store;
}

bool BinaryStore::loadSerializedData(std::optional<std::string> aliasBlobBaseId)
{
    /* Load blob from sysfile if we know it might not match what we have.
     * Note it will overwrite existing unsaved data per design. */
    if (commitState_ == CommitState::Clean ||
        commitState_ == CommitState::Uninitialized)
    {
        return true;
    }

    log<level::NOTICE>("Try loading blob from persistent data",
                       entry("BASE_ID=%s", baseBlobId_.c_str()));
    try
    {
        /* Parse length-prefixed format to protobuf */
        boost::endian::little_uint64_t size = 0;
        file_->readToBuf(0, sizeof(size), reinterpret_cast<char*>(&size));

        if (!blob_.ParseFromString(file_->readAsStr(sizeof(uint64_t), size)))
        {
            /* Fail to parse the data, which might mean no preexsiting blobs
             * and is a valid case to handle. Simply init an empty binstore. */
            commitState_ = CommitState::Uninitialized;
        }
    }
    catch (const std::system_error& e)
    {
        /* Read causes unexpected system-level failure */
        log<level::ERR>("Reading from sysfile failed",
                        entry("ERROR=%s", e.what()));
        return false;
    }
    catch (const std::exception& e)
    {
        /* Non system error originates from junk value in 'size' */
        commitState_ = CommitState::Uninitialized;
    }

    if (commitState_ == CommitState::Uninitialized)
    {
        log<level::WARNING>("Fail to parse. There might be no persisted blobs",
                            entry("BASE_ID=%s", baseBlobId_.c_str()));
        return true;
    }

    std::string alias = aliasBlobBaseId.value_or("");
    if (blob_.blob_base_id() == alias)
    {
        log<level::WARNING>("Alias blob id, rename blob id...",
                            entry("LOADED=%s", alias.c_str()),
                            entry("RENAMED=%s", baseBlobId_.c_str()));
        std::string tmpBlobId = baseBlobId_;
        baseBlobId_ = alias;
        return setBaseBlobId(tmpBlobId);
    }
    if (blob_.blob_base_id() != baseBlobId_ && !readOnly_)
    {
        /* Uh oh, stale data loaded. Clean it and commit. */
        // TODO: it might be safer to add an option in config to error out
        // instead of to overwrite.
        log<level::ERR>("Stale blob data, resetting internals...",
                        entry("LOADED=%s", blob_.blob_base_id().c_str()),
                        entry("EXPECTED=%s", baseBlobId_.c_str()));
        blob_.Clear();
        blob_.set_blob_base_id(baseBlobId_);
        return this->commit();
    }

    return true;
}

std::string BinaryStore::getBaseBlobId() const
{
    if (!baseBlobId_.empty())
    {
        return baseBlobId_;
    }

    return blob_.blob_base_id();
}

bool BinaryStore::setBaseBlobId(const std::string& baseBlobId)
{
    if (baseBlobId_.empty())
    {
        baseBlobId_ = blob_.blob_base_id();
    }

    std::string oldBlobId = baseBlobId_;
    size_t oldPrefixIndex = baseBlobId_.size();
    baseBlobId_ = baseBlobId;
    blob_.set_blob_base_id(baseBlobId_);
    auto blobsPtr = blob_.mutable_blobs();
    for (auto blob = blobsPtr->begin(); blob != blobsPtr->end(); blob++)
    {
        const std::string& blodId = blob->blob_id();
        if (blodId.starts_with(oldBlobId))
        {
            blob->set_blob_id(baseBlobId_ + blodId.substr(oldPrefixIndex));
        }
    }
    return this->commit();
}

std::vector<std::string> BinaryStore::getBlobIds() const
{
    std::vector<std::string> result;
    result.reserve(blob_.blobs().size() + 1);
    result.emplace_back(getBaseBlobId());
    std::for_each(
        blob_.blobs().begin(), blob_.blobs().end(),
        [&result](const auto& blob) { result.emplace_back(blob.blob_id()); });

    return result;
}

bool BinaryStore::openOrCreateBlob(const std::string& blobId, uint16_t flags)
{
    if (!(flags & blobs::OpenFlags::read))
    {
        log<level::ERR>("OpenFlags::read not specified when opening",
                        entry("BLOB_ID=%s", blobId.c_str()));
        return false;
    }

    if (currentBlob_ && (currentBlob_->blob_id() != blobId))
    {
        log<level::ERR>("Already handling a different blob",
                        entry("EXPECTED=%s", currentBlob_->blob_id().c_str()),
                        entry("RECEIVED=%s", blobId.c_str()));
        return false;
    }

    if (readOnly_ && (flags & blobs::OpenFlags::write))
    {
        log<level::ERR>("Can't open the blob for writing: read-only store",
                        entry("BLOB_ID=%s", blobId.c_str()));
        return false;
    }

    writable_ = flags & blobs::OpenFlags::write;

    /* If there are uncommitted data, discard them. */
    if (!this->loadSerializedData())
    {
        return false;
    }

    /* Iterate and find if there is an existing blob with this id.
     * blobsPtr points to a BinaryBlob container with STL-like semantics*/
    auto blobsPtr = blob_.mutable_blobs();
    auto blobIt =
        std::find_if(blobsPtr->begin(), blobsPtr->end(),
                     [&](const auto& b) { return b.blob_id() == blobId; });

    if (blobIt != blobsPtr->end())
    {
        currentBlob_ = &(*blobIt);
        return true;
    }

    /* Otherwise, create the blob and append it */
    if (readOnly_)
    {
        return false;
    }
    else
    {
        currentBlob_ = blob_.add_blobs();
        currentBlob_->set_blob_id(blobId);

        commitState_ = CommitState::Dirty;
        log<level::NOTICE>("Created new blob",
                           entry("BLOB_ID=%s", blobId.c_str()));
    }

    return true;
}

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

std::vector<uint8_t> BinaryStore::read(uint32_t offset, uint32_t requestedSize)
{
    std::vector<uint8_t> result;

    if (!currentBlob_)
    {
        log<level::ERR>("No open blob to read");
        return result;
    }

    auto dataPtr = currentBlob_->mutable_data();

    /* If it is out of bound, return empty vector */
    if (offset >= dataPtr->size())
    {
        log<level::ERR>("Read offset is beyond data size",
                        entry("MAX_SIZE=0x%x", dataPtr->size()),
                        entry("RECEIVED_OFFSET=0x%x", offset));
        return result;
    }

    uint32_t requestedEndPos = offset + requestedSize;

    result = std::vector<uint8_t>(
        dataPtr->begin() + offset,
        std::min(dataPtr->begin() + requestedEndPos, dataPtr->end()));
    return result;
}

std::vector<uint8_t> BinaryStore::readBlob(const std::string& blobId) const
{
    const auto blobs = blob_.blobs();
    const auto blobIt =
        std::find_if(blobs.begin(), blobs.end(),
                     [&](const auto& b) { return b.blob_id() == blobId; });

    if (blobIt == blobs.end())
    {
        throw ipmi::HandlerCompletion(ipmi::ccUnspecifiedError);
    }

    const auto blobData = blobIt->data();

    return std::vector<uint8_t>(blobData.begin(), blobData.end());
}

bool BinaryStore::write(uint32_t offset, const std::vector<uint8_t>& data)
{
    if (!currentBlob_)
    {
        log<level::ERR>("No open blob to write");
        return false;
    }

    if (!writable_)
    {
        log<level::ERR>("Open blob is not writable");
        return false;
    }

    auto dataPtr = currentBlob_->mutable_data();

    if (offset > dataPtr->size())
    {
        log<level::ERR>("Write would leave a gap with undefined data. Return.");
        return false;
    }

    bool needResize = offset + data.size() > dataPtr->size();

    // current size is the binary blob proto size + uint64 tracking the total
    // size of the binary blob.
    // currentSize = blob_size + x (uint64_t), where x = blob_size.
    size_t currentSize = blob_.SerializeAsString().size() +
                         sizeof(boost::endian::little_uint64_t);
    size_t sizeDelta = needResize ? offset + data.size() - dataPtr->size() : 0;

    if (maxSize && currentSize + sizeDelta > *maxSize)
    {
        log<level::ERR>("Write data would make the total size exceed the max "
                        "size allowed. Return.");
        return false;
    }

    commitState_ = CommitState::Dirty;
    /* Copy (overwrite) the data */
    if (needResize)
    {
        dataPtr->resize(offset + data.size()); // not enough space, extend
    }
    std::copy(data.begin(), data.end(), dataPtr->begin() + offset);
    return true;
}

bool BinaryStore::commit()
{
    if (readOnly_)
    {
        log<level::ERR>("ReadOnly blob, not committing");
        return false;
    }

    /* Store as little endian to be platform agnostic. Consistent with read. */
    auto blobData = blob_.SerializeAsString();
    boost::endian::little_uint64_t sizeLE = blobData.size();
    std::string commitData(reinterpret_cast<const char*>(sizeLE.data()),
                           sizeof(sizeLE));
    commitData += blobData;

    // This should never be true if it is blocked by the write command
    if (maxSize && sizeof(commitData) > *maxSize)
    {
        log<level::ERR>("Commit Data exceeded maximum allowed size");
        return false;
    }

    try
    {
        file_->writeStr(commitData, 0);
    }
    catch (const std::exception& e)
    {
        commitState_ = CommitState::CommitError;
        log<level::ERR>("Writing to sysfile failed",
                        entry("ERROR=%s", e.what()));
        return false;
    };

    commitState_ = CommitState::Clean;
    return true;
}

bool BinaryStore::close()
{
    currentBlob_ = nullptr;
    writable_ = false;
    commitState_ = CommitState::Dirty;
    return true;
}

/*
 * Sets |meta| with size and state of the blob. Returns |blobState| with
 * standard definition from phosphor-ipmi-blobs header blob.hpp, plus OEM
 * flag bits BinaryStore::CommitState.

enum StateFlags
{
    open_read = (1 << 0),
    open_write = (1 << 1),
    committing = (1 << 2),
    committed = (1 << 3),
    commit_error = (1 << 4),
};

enum CommitState
{
    Dirty = (1 << 8), // In-memory data might not match persisted data
    Clean = (1 << 9), // In-memory data matches persisted data
    Uninitialized = (1 << 10), // Cannot find persisted data
    CommitError = (1 << 11)    // Error happened during committing
};

*/
bool BinaryStore::stat(blobs::BlobMeta* meta)
{
    uint16_t blobState = blobs::StateFlags::open_read;
    if (writable_)
    {
        blobState |= blobs::StateFlags::open_write;
    }

    if (commitState_ == CommitState::Clean)
    {
        blobState |= blobs::StateFlags::committed;
    }
    else if (commitState_ == CommitState::CommitError)
    {
        blobState |= blobs::StateFlags::commit_error;
    }
    blobState |= commitState_;

    if (currentBlob_)
    {
        meta->size = currentBlob_->data().size();
    }
    else
    {
        meta->size = 0;
    }
    meta->blobState = blobState;

    return true;
}

} // namespace binstore
