// Copyright 2021 Google Inc.
//
// 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 "log_handler.hpp"

#include <algorithm>
#include <cstring>
#include <ios>
#include <limits>
#include <memory>
#include <optional>
#include <utility>
#include <vector>

namespace ipmi_flash
{

LogBlobHandler::LogBlobHandler(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,
                            "LogBlobHandler: Log file unit failed for %s\n",
                            infoP->blobId.c_str());
                    continue;
                }
                if (!infoP->handler->open("", std::ios::in))
                {
                    fprintf(stderr,
                            "LogBlobHandler: Opening log 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,
                            "LogBlobHandler: Reading log 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,
                    "LogBlobHandler: Ignoring duplicate config for %s\n",
                    info->blobId.c_str());
        }
    }
}

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

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

/**
 * deleteBlob - does nothing, always fails
 */
bool LogBlobHandler::deleteBlob(const std::string& path)
{
    for (const auto& [sessionId, sessionInfo] : sessionInfoMap)
    {
        if (sessionInfo->blob->blobId == path)
        {
            fprintf(stderr,
                    "LogBlobHandler: delete %s fail: there is an open session "
                    "for this blob\n",
                    path.c_str());
            return false;
        }
    }

    auto* blob = blobInfoMap.at(path).get();
    if (!blob->actions->onDelete->trigger())
    {
        fprintf(stderr,
                "LogBlobHandler: delete %s fail: onDelete trigger failed\n",
                path.c_str());
        return false;
    }
    return true;
}

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

bool LogBlobHandler::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,
                "LogBlobHandler: 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, "LogBlobHandler: 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> LogBlobHandler::read(uint16_t session, uint32_t offset,
                                          uint32_t requestedSize)
{
    auto& data = sessionInfoMap.at(session)->data;
    if (data == nullptr || !*data)
    {
        throw std::runtime_error("LogBlobHandler: Log 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 LogBlobHandler::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 LogBlobHandler::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 LogBlobHandler::expire(uint16_t session)
{
    close(session);
    return true;
}

} // namespace ipmi_flash
