/*
 * 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 "helper.hpp"
#include "status.hpp"
#include "tool_errors.hpp"
#include "util.hpp"

#include <algorithm>
#include <blobs-ipmid/blobs.hpp>
#include <cstdint>
#include <cstring>
#include <ipmiblob/blob_errors.hpp>
#include <string>
#include <vector>

namespace host_tool
{

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;
    }

    /* Call stat on /flash/image (or /flash/tarball) and check if data interface
     * is supported.
     */
    ipmiblob::StatResponse stat;

    try
    {
        stat = blob->getStat(goalFirmware);
    }
    catch (const ipmiblob::BlobException& b)
    {
        std::fprintf(stderr, "Received exception '%s' on getStat\n", b.what());
        return false;
    }

    auto supported = handler->supportedType();
    if ((stat.blob_state & supported) == 0)
    {
        std::fprintf(stderr, "data interface selected not supported.\n");
        return false;
    }

    return true;
}

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

    try
    {
        session = blob->openBlob(
            target, static_cast<std::uint16_t>(supported) |
                        static_cast<std::uint16_t>(blobs::OpenFlags::write));
    }
    catch (const ipmiblob::BlobException& b)
    {
        throw ToolException("blob exception received: " +
                            std::string(b.what()));
    }

    if (!handler->sendContents(path, session))
    {
        /* Need to close the session on failure, or it's stuck open (until the
         * blob handler timeout is implemented, and even then, why make it wait.
         */
        blob->closeBlob(session);
        throw ToolException("Failed to send contents of " + path);
    }

    blob->closeBlob(session);
}

bool UpdateHandler::verifyFile(const std::string& target)
{
    std::uint16_t session;
    bool success = false;

    try
    {
        session = blob->openBlob(
            target, static_cast<std::uint16_t>(blobs::OpenFlags::write));
    }
    catch (const ipmiblob::BlobException& b)
    {
        throw ToolException("blob exception received: " +
                            std::string(b.what()));
    }

    std::fprintf(stderr, "Committing to %s to trigger service\n",
                 target.c_str());

    try
    {
        blob->commit(session, {});
    }
    catch (const ipmiblob::BlobException& b)
    {
        blob->closeBlob(session);
        throw ToolException("blob exception received: " +
                            std::string(b.what()));
    }

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

    if (pollStatus(session, blob))
    {
        std::fprintf(stderr, "Returned success\n");
        success = true;
    }
    else
    {
        std::fprintf(stderr, "Returned non-success (could still "
                             "be running (unlikely))\n");
    }

    blob->closeBlob(session);
    return (success == true);
}

void UpdateHandler::cleanArtifacts()
{
    /* open(), commit(), close() */
    std::uint16_t session;

    /* Errors aren't important for this call. */
    try
    {
        std::fprintf(stderr, "Opening the cleanup blob\n");
        session =
            blob->openBlob(ipmi_flash::cleanupBlobId,
                           static_cast<std::uint16_t>(blobs::OpenFlags::write));
    }
    catch (...)
    {
        return;
    }

    try
    {
        std::fprintf(stderr, "Committing to the cleanup blob\n");
        blob->commit(session, {});
        std::fprintf(stderr, "Closing cleanup blob\n");
    }
    catch (...)
    {
    }

    blob->closeBlob(session);
}

} // namespace host_tool
