/*
 * Copyright 2018 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 "handler.hpp"

#include "flags.hpp"
#include "helper.hpp"
#include "status.hpp"
#include "tool_errors.hpp"
#include "util.hpp"

#include <ipmiblob/blob_errors.hpp>
#include <stdplus/handle/managed.hpp>

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>

namespace host_tool
{

static void closeBlob(uint16_t&& session, ipmiblob::BlobInterface*& blob)
{
    blob->closeBlob(session);
}

using BlobHandle =
    stdplus::Managed<uint16_t, ipmiblob::BlobInterface*>::Handle<closeBlob>;

template <typename... Args>
inline BlobHandle openBlob(ipmiblob::BlobInterface* blob, Args&&... args)
{
    return BlobHandle(blob->openBlob(std::forward<Args>(args)...), blob);
}

bool UpdateHandler::checkAvailable(const std::string& goalFirmware)
{
    std::vector<std::string> blobs = blob->getBlobList();

    auto blobInst = std::find_if(
        blobs.begin(), blobs.end(), [&goalFirmware](const std::string& iter) {
            /* Running into weird scenarios where the string comparison doesn't
             * work.  TODO: revisit.
             */
            return (0 == std::memcmp(goalFirmware.c_str(), iter.c_str(),
                                     goalFirmware.length()));
            // return (goalFirmware.compare(iter));
        });
    if (blobInst == blobs.end())
    {
        std::fprintf(stderr, "%s not found\n", goalFirmware.c_str());
        return false;
    }

    return true;
}

void UpdateHandler::sendFile(const std::string& target, const std::string& path)
{
    auto supported = handler->supportedType();

    try
    {
        auto session = openBlob(
            blob, target,
            static_cast<std::uint16_t>(supported) |
                static_cast<std::uint16_t>(
                    ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));

        if (!handler->sendContents(path, *session))
        {
            throw ToolException("Failed to send contents of " + path);
        }
    }
    catch (const ipmiblob::BlobException& b)
    {
        throw ToolException("blob exception received: " +
                            std::string(b.what()));
    }
}

bool UpdateHandler::verifyFile(const std::string& target, bool ignoreStatus)
{
    try
    {
        auto session =
            openBlob(blob, target,
                     static_cast<std::uint16_t>(
                         ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));

        std::fprintf(stderr, "Committing to %s to trigger service\n",
                     target.c_str());
        blob->commit(*session, {});

        if (ignoreStatus)
        {
            // Skip checking the blob for status if ignoreStatus is enabled
            return true;
        }

        std::fprintf(stderr, "Calling stat on %s session to check status\n",
                     target.c_str());
        pollStatus(*session, blob);
        return true;
    }
    catch (const ipmiblob::BlobException& b)
    {
        throw ToolException("blob exception received: " +
                            std::string(b.what()));
    }
}

std::vector<uint8_t> UpdateHandler::readVersion(const std::string& versionBlob)
{
    try
    {
        auto session =
            openBlob(blob, versionBlob,
                     static_cast<std::uint16_t>(
                         ipmi_flash::FirmwareFlags::UpdateFlags::openRead));

        std::fprintf(stderr, "Calling stat on %s session to check status\n",
                     versionBlob.c_str());

        /* TODO: call readBytes multiple times in case IPMI message length
         * exceeds IPMI_MAX_MSG_LENGTH.
         */
        auto size = pollReadReady(*session, blob);
        if (size > 0)
        {
            return blob->readBytes(*session, 0, size);
        }
        return {};
    }
    catch (const ipmiblob::BlobException& b)
    {
        throw ToolException("blob exception received: " +
                            std::string(b.what()));
    }
}

void UpdateHandler::cleanArtifacts()
{
    /* Errors aren't important for this call. */
    try
    {
        std::fprintf(stderr, "Executing cleanup blob\n");
        auto session =
            openBlob(blob, ipmi_flash::cleanupBlobId,
                     static_cast<std::uint16_t>(
                         ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));
        blob->commit(*session, {});
    }
    catch (const std::exception& e)
    {
        std::fprintf(stderr, "Cleanup failed: %s\n", e.what());
    }
}

} // namespace host_tool
