/*
 * 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 "updater.hpp"

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

#include <ipmiblob/blob_errors.hpp>

#include <algorithm>
#include <cstring>
#include <memory>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>

namespace host_tool
{

void updaterMain(UpdateHandlerInterface* updater, ipmiblob::BlobInterface* blob,
                 const std::string& imagePath, const std::string& signaturePath,
                 const std::string& layoutType, bool ignoreUpdate)
{
    /* TODO: validate the layoutType isn't a special value such as: 'update',
     * 'verify', or 'hash'
     */
    std::string layout = "/flash/" + layoutType;

    bool goalSupported = updater->checkAvailable(layout);
    if (!goalSupported)
    {
        throw ToolException("Goal firmware not supported");
    }

    // Clean all active blobs to support multiple stages
    // Check for any active blobs and delete the first one found to reset the
    // BMC's phosphor-ipmi-flash state machine then clean any leftover artifacts
    const auto blobList = blob->getBlobList();
    for (const auto& activeBlob : blobList)
    {
        // Prefix is /flash/active/
        if (activeBlob.starts_with("/flash/active/"))
        {
            std::fprintf(stderr, "Found an active blob, deleting %s\n",
                         activeBlob.c_str());
            blob->deleteBlob(activeBlob);
            updater->cleanArtifacts();
            break;
        }
    }

    /* Yay, our layout type is supported. */
    try
    {
        /* Send over the firmware image. */
        std::fprintf(stderr, "Sending over the firmware image.\n");
        updater->sendFile(layout, imagePath);

        /* Send over the hash contents. */
        std::fprintf(stderr, "Sending over the hash file.\n");
        updater->sendFile(ipmi_flash::hashBlobId, signaturePath);

        /* Trigger the verification by opening and committing the verify file.
         */
        std::fprintf(stderr, "Opening the verification file\n");
        if (updater->verifyFile(ipmi_flash::verifyBlobId, false))
        {
            std::fprintf(stderr, "succeeded\n");
        }
        else
        {
            std::fprintf(stderr, "failed\n");
            throw ToolException("Verification failed");
        }

        /* Trigger the update by opening and committing the update file. */
        std::fprintf(stderr, "Opening the update file\n");
        if (updater->verifyFile(ipmi_flash::updateBlobId, ignoreUpdate))
        {
            std::fprintf(stderr, "succeeded\n");
        }
        else
        {
            /* Depending on the update mechanism used, this may be
             * uninteresting. For instance, for the static layout, we use the
             * reboot update mechanism.  Which doesn't always lead to a
             * successful return before the BMC starts shutting down services.
             */
            std::fprintf(stderr, "failed\n");
            throw ToolException("Update failed");
        }
    }
    catch (...)
    {
        updater->cleanArtifacts();
        throw;
    }
}

} // namespace host_tool
