/*
 * 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 "fs.hpp"
#include "general_systemd.hpp"
#include "prepare_systemd.hpp"
#include "update_systemd.hpp"

#include <algorithm>
#include <cstdio>
#include <exception>
#include <fstream>
#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <string>
#include <vector>

namespace ipmi_flash
{

std::unique_ptr<TriggerableActionInterface>
    buildFileSystemd(const nlohmann::json& data)
{
    /* This type of action requires a path and unit, and optionally a mode. */
    const auto& path = data.at("path");
    const auto& unit = data.at("unit");

    /* the mode parameter is optional. */
    std::string systemdMode = "replace";
    const auto& mode = data.find("mode");
    if (mode != data.end())
    {
        systemdMode = data.at("mode").get<std::string>();
    }

    return SystemdWithStatusFile::CreateSystemdWithStatusFile(
        sdbusplus::bus::new_default(), path, unit, systemdMode);
}

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")
            {
                pack->verification = std::move(buildFileSystemd(verify));
            }
            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 == "fileSystemdUpdate")
            {
                pack->update = std::move(buildFileSystemd(update));
            }
            else if (updateType == "systemd")
            {
                const auto& unit = update.at("unit");

                /* the mode parameter is optional. */
                std::string systemdMode = "replace";
                const auto& mode = update.find("mode");
                if (mode != update.end())
                {
                    systemdMode = update.at("mode").get<std::string>();
                }

                pack->update = SystemdUpdateMechanism::CreateSystemdUpdate(
                    sdbusplus::bus::new_default(), unit, systemdMode);
            }
            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;
}

std::vector<HandlerConfig> BuildHandlerConfigs(const std::string& directory)
{
    using namespace phosphor::logging;

    std::vector<HandlerConfig> output;

    std::vector<std::string> jsonPaths = GetJsonList(directory);

    for (const auto& path : jsonPaths)
    {
        std::ifstream jsonFile(path);
        if (!jsonFile.is_open())
        {
            log<level::ERR>("Unable to open json file",
                            entry("PATH=%s", path.c_str()));
            continue;
        }

        auto data = nlohmann::json::parse(jsonFile, nullptr, false);
        if (data.is_discarded())
        {
            log<level::ERR>("Parsing json failed",
                            entry("PATH=%s", path.c_str()));
            continue;
        }

        std::vector<HandlerConfig> configs = buildHandlerFromJson(data);
        std::move(configs.begin(), configs.end(), std::back_inserter(output));
    }

    return output;
}

} // namespace ipmi_flash
