// Copyright 2021 Google LLC
//
// 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 <flashupdate/config.hpp>
#include <nlohmann/json.hpp>

#include <format>
#include <fstream>
#include <optional>

namespace flashupdate
{

Config createConfig(std::optional<std::string> configFile, uint8_t stagingIndex,
                    const std::string& configPath)
{
    if (!configFile)
    {
        throw std::runtime_error("Configuration file is missing");
    }

    Config config;
    std::string name = *configFile;

    // Not full file path
    if (name.find(".") == std::string::npos &&
        name.find("/") == std::string::npos)
    {
        name = configPath + name + ".json";
    }

    std::ifstream configJson(name);
    if (!configJson.is_open())
    {
        throw std::runtime_error(
            std::format("Config file `{}` is missing", name));
    }

    auto data = nlohmann::json::parse(configJson, nullptr, false);
    if (data.is_discarded())
    {
        throw std::runtime_error("failed to parse the config.json");
    }
    auto flash = data.at("flash");
    flash.at("validation_key").get_to(config.flash.validationKey);

    auto primary = flash.at("primary");
    primary.at("location").get_to(config.flash.primary.location);

    auto muxSelect = primary.at("mux_select");
    if (muxSelect.is_null())
    {
        throw std::runtime_error(
            "mux_select for primary partition is required");
    }
    uint16_t mux;
    muxSelect.get_to(mux);
    config.flash.primary.muxSelect = mux;

    auto secondaries = flash.at("secondary");
    for (const auto& secondary : secondaries)
    {
        Config::Partition partition;

        secondary.at("location").get_to(partition.location);

        auto muxSelect = secondary.at("mux_select");

        if (!muxSelect.is_null())
        {
            muxSelect.get_to(mux);
            partition.muxSelect = mux;
        }

        config.flash.secondary.emplace_back(partition);
    }

    if (stagingIndex >= secondaries.size())
    {
        throw std::runtime_error(std::format(
            "stage index is greater than or equal to the number of staging "
            "partitions: {} >= {}",
            stagingIndex, secondaries.size()));
    }
    config.flash.stagingIndex = stagingIndex;

    flash.at("device_id").get_to(config.flash.deviceId);
    flash.at("driver").get_to(config.flash.driver);

    auto metadata = data.at("metadata");
    metadata.at("path").get_to(config.metadata.path);
    metadata.at("offset").get_to(config.metadata.offset);

    auto cr51 = data.at("cr51");

    if (!cr51.is_null())
    {
        Config::Cr51 cr51Config;
        cr51.at("prod_to_dev").get_to(cr51Config.prodToDev);
        cr51.at("production_mode").get_to(cr51Config.productionMode);
        cr51.at("unsigned_to_dev").get_to(cr51Config.unsignedToDev);

        if (cr51.contains("image_family"))
        {
            cr51.at("image_family").get_to(cr51Config.imageFamily.emplace());
        }

        config.cr51 = cr51Config;
    }

    if (data.contains("supported_version"))
    {
        config.supportedVersion = std::vector<Config::SupportedVersion>();
        auto supportedVersion = data.at("supported_version");

        for (const auto& version : supportedVersion.items())
        {
            Config::SupportedVersion currentVersion;
            if (version.value().contains("min"))
            {
                auto minVersion = version.value().at("min");
                currentVersion.min = version::Version();
                minVersion.at("major").get_to(currentVersion.min->major);
                minVersion.at("minor").get_to(currentVersion.min->minor);
                minVersion.at("point").get_to(currentVersion.min->point);
                minVersion.at("subpoint").get_to(currentVersion.min->subpoint);
            }
            if (version.value().contains("max"))
            {
                auto maxVersion = version.value().at("max");
                currentVersion.max = version::Version();
                maxVersion.at("major").get_to(currentVersion.max->major);
                maxVersion.at("minor").get_to(currentVersion.max->minor);
                maxVersion.at("point").get_to(currentVersion.max->point);
                maxVersion.at("subpoint").get_to(currentVersion.max->subpoint);
            }

            if (currentVersion.min == std::nullopt &&
                currentVersion.max == std::nullopt)
            {
                continue;
            }

            config.supportedVersion->emplace_back(currentVersion);
        }
    }

    return config;
}

} // namespace flashupdate
