/*
 * Copyright 2019 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 "buildjson.hpp"

#include "file_handler.hpp"
#include "prepare_systemd.hpp"
#include "update_systemd.hpp"
#include "verify_systemd.hpp"

#include <cstdio>
#include <exception>
#include <nlohmann/json.hpp>
#include <sdbusplus/bus.hpp>
#include <string>
#include <vector>

namespace ipmi_flash
{

std::vector<HandlerConfig> buildHandlerFromJson(const nlohmann::json& data)
{
    std::vector<HandlerConfig> handlers;

    for (const auto& item : data)
    {
        try
        {
            HandlerConfig output;

            /* at() throws an exception when the key is not present. */
            item.at("blob").get_to(output.blobId);

            /* handler is required. */
            const auto& h = item.at("handler");
            const std::string handlerType = h.at("type");
            if (handlerType == "file")
            {
                const auto& path = h.at("path");
                output.handler = std::make_unique<FileHandler>(path);
            }
            else
            {
                throw std::runtime_error("Invalid handler type: " +
                                         handlerType);
            }

            /* actions are required (presently). */
            const auto& a = item.at("actions");
            std::unique_ptr<ActionPack> pack = std::make_unique<ActionPack>();

            /* It hasn't been fully determined if any action being optional is
             * useful, so for now they will be required.
             * TODO: Evaluate how the behaviors change if some actions are
             * missing, does the code just assume it was successful?  I would
             * think not.
             */
            const auto& prep = a.at("preparation");
            const std::string prepareType = prep.at("type");
            if (prepareType == "systemd")
            {
                const auto& unit = prep.at("unit");
                pack->preparation = SystemdPreparation::CreatePreparation(
                    sdbusplus::bus::new_default(), unit);
            }
            else
            {
                throw std::runtime_error("Invalid preparation type: " +
                                         prepareType);
            }

            const auto& verify = a.at("verification");
            const std::string verifyType = verify.at("type");
            if (verifyType == "fileSystemdVerify")
            {
                const auto& path = verify.at("path");
                const auto& unit = verify.at("unit");
                pack->verification = SystemdVerification::CreateVerification(
                    sdbusplus::bus::new_default(), path, unit);
            }
            else
            {
                throw std::runtime_error("Invalid verification type:" +
                                         verifyType);
            }

            const auto& update = a.at("update");
            const std::string updateType = update.at("type");
            if (updateType == "reboot")
            {
                static constexpr auto rebootTarget = "reboot.target";
                static constexpr auto rebootMode = "replace-irreversibly";
                pack->update = SystemdUpdateMechanism::CreateSystemdUpdate(
                    sdbusplus::bus::new_default(), rebootTarget, rebootMode);
            }
            else if (updateType == "systemd")
            {
                const auto& unit = update.at("unit");
                pack->update = SystemdUpdateMechanism::CreateSystemdUpdate(
                    sdbusplus::bus::new_default(), unit);
            }
            else
            {
                throw std::runtime_error("Invalid update type: " + updateType);
            }

            output.actions = std::move(pack);
            handlers.push_back(std::move(output));
        }
        catch (const std::exception& e)
        {
            /* TODO: Once phosphor-logging supports unit-test injection, fix
             * this to log.
             */
            std::fprintf(stderr,
                         "Excepted building HandlerConfig from json: %s\n",
                         e.what());
        }
    }

    return handlers;
}

} // namespace ipmi_flash
