/*
 * 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 <algorithm>
#include <cstring>
#include <ipmiblob/blob_errors.hpp>
#include <memory>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>

namespace host_tool
{

void updaterMain(UpdateHandlerInterface* updater, const std::string& imagePath,
                 const std::string& signaturePath,
                 const std::string& layoutType)
{
    static std::unordered_map<std::string, std::string> typesToBlob = {
        {"static", ipmi_flash::staticLayoutBlobId},
        {"ubitar", ipmi_flash::ubiTarballBlobId},
        {"bios", ipmi_flash::biosBlobId}};
    /* We know it's one of the above types already. */
    auto& layout = typesToBlob[layoutType];

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

    /* Yay, our data handler 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))
        {
            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))
        {
            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
