/*
// Copyright (c) 2018 Intel Corporation
//
// 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 "Overlay.hpp"

#include "Utils.hpp"
#include "devices.hpp"

#include <boost/algorithm/string/predicate.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <boost/process/child.hpp>
#include <filesystem>
#include <iomanip>
#include <iostream>
#include <nlohmann/json.hpp>
#include <regex>
#include <string>

constexpr const char* DT_OVERLAY = "/usr/bin/dtoverlay";
constexpr const char* DTC = "/usr/bin/dtc";
constexpr const char* OUTPUT_DIR = "/tmp/overlays";
constexpr const char* TEMPLATE_DIR = PACKAGE_DIR "overlay_templates";
constexpr const char* TEMPLATE_CHAR = "$";
constexpr const char* HEX_FORMAT_STR = "0x";
constexpr const char* PLATFORM = "aspeed,ast2500";
constexpr const char* I2C_DEVS_DIR = "/sys/bus/i2c/devices";
constexpr const char* MUX_SYMLINK_DIR = "/dev/i2c-mux";

constexpr const bool DEBUG = false;

// some drivers need to be unbind / bind to load device tree changes
static const boost::container::flat_map<std::string, std::string> FORCE_PROBES =
    {{"IntelFanConnector", "/sys/bus/platform/drivers/aspeed_pwm_tacho"}};

std::regex ILLEGAL_NAME_REGEX("[^A-Za-z0-9_]");

void createOverlay(const std::string& templatePath,
                   const nlohmann::json& configuration);

void unloadAllOverlays(void)
{
    boost::process::child c(DT_OVERLAY, "-d", OUTPUT_DIR, "-R");
    c.wait();
}

// this is hopefully temporary, but some drivers can't detect changes
// without an unbind and bind so this function must exist for now
void forceProbe(const std::string& driver)
{
    std::ofstream driverUnbind(driver + "/unbind");
    std::ofstream driverBind(driver + "/bind");
    if (!driverUnbind.is_open())
    {
        std::cerr << "force probe error opening " << driver << "\n";
        return;
    }
    if (!driverBind.is_open())
    {
        driverUnbind.close();
        std::cerr << "force probe error opening " << driver << "\n";
        return;
    }

    std::filesystem::path pathObj(driver);
    for (auto& p : std::filesystem::directory_iterator(pathObj))
    {
        // symlinks are object names
        if (is_symlink(p))
        {
            std::string driverName = p.path().filename();
            driverUnbind << driverName;
            driverBind << driverName;
            break;
        }
    }
    driverUnbind.close();
    driverBind.close();
}

// helper function to make json types into string
std::string jsonToString(const nlohmann::json& in)
{
    if (in.type() == nlohmann::json::value_t::string)
    {
        return in.get<std::string>();
    }
    else if (in.type() == nlohmann::json::value_t::array)
    {
        // remove brackets and comma from array
        std::string array = in.dump();
        array = array.substr(1, array.size() - 2);
        boost::replace_all(array, ",", " ");
        return array;
    }
    return in.dump();
}

void linkMux(const std::string& muxName, size_t busIndex, size_t address,
             const nlohmann::json::array_t& channelNames)
{
    std::error_code ec;
    std::filesystem::path muxSymlinkDir(MUX_SYMLINK_DIR);
    std::filesystem::create_directory(muxSymlinkDir, ec);
    // ignore error codes here if the directory already exists
    ec.clear();
    std::filesystem::path linkDir = muxSymlinkDir / muxName;
    std::filesystem::create_directory(linkDir, ec);

    std::ostringstream hexAddress;
    hexAddress << std::hex << std::setfill('0') << std::setw(4) << address;

    std::filesystem::path devDir(I2C_DEVS_DIR);
    devDir /= std::to_string(busIndex) + "-" + hexAddress.str();

    for (std::size_t channelIndex = 0; channelIndex < channelNames.size();
         channelIndex++)
    {
        const std::string* channelName =
            channelNames[channelIndex].get_ptr<const std::string*>();
        if (channelName == nullptr)
        {
            continue;
        }
        if (channelName->empty())
        {
            continue;
        }

        std::filesystem::path channelPath =
            devDir / ("channel-" + std::to_string(channelIndex));
        if (!is_symlink(channelPath))
        {
            std::cerr << channelPath << "for mux channel " << *channelName
                      << " doesn't exist!\n";
            continue;
        }
        std::filesystem::path bus = std::filesystem::read_symlink(channelPath);

        std::filesystem::path fp("/dev" / bus.filename());
        std::filesystem::path link(linkDir / *channelName);

        std::filesystem::create_symlink(fp, link, ec);
        if (ec)
        {
            std::cerr << "Failure creating symlink for " << fp << " to " << link
                      << "\n";
        }
    }
}

void exportDevice(const std::string& type,
                  const devices::ExportTemplate& exportTemplate,
                  const nlohmann::json& configuration)
{

    std::string parameters = exportTemplate.parameters;
    std::string device = exportTemplate.device;
    std::string name = "unknown";
    const uint64_t* bus = nullptr;
    const uint64_t* address = nullptr;
    const nlohmann::json::array_t* channels = nullptr;

    for (auto keyPair = configuration.begin(); keyPair != configuration.end();
         keyPair++)
    {
        std::string subsituteString;

        if (keyPair.key() == "Name" &&
            keyPair.value().type() == nlohmann::json::value_t::string)
        {
            subsituteString = std::regex_replace(
                keyPair.value().get<std::string>(), ILLEGAL_NAME_REGEX, "_");
            name = subsituteString;
        }
        else
        {
            subsituteString = jsonToString(keyPair.value());
        }

        if (keyPair.key() == "Bus")
        {
            bus = keyPair.value().get_ptr<const uint64_t*>();
        }
        else if (keyPair.key() == "Address")
        {
            address = keyPair.value().get_ptr<const uint64_t*>();
        }
        else if (keyPair.key() == "ChannelNames")
        {
            channels =
                keyPair.value().get_ptr<const nlohmann::json::array_t*>();
        }
        boost::replace_all(parameters, TEMPLATE_CHAR + keyPair.key(),
                           subsituteString);
        boost::replace_all(device, TEMPLATE_CHAR + keyPair.key(),
                           subsituteString);
    }

    // if we found bus and address we can attempt to prevent errors
    if (bus != nullptr && address != nullptr)
    {
        std::ostringstream hex;
        hex << std::hex << *address;
        const std::string& addressHex = hex.str();
        std::string busStr = std::to_string(*bus);

        std::filesystem::path devicePath(device);
        std::filesystem::path parentPath = devicePath.parent_path();
        if (std::filesystem::is_directory(parentPath))
        {
            for (const auto& path :
                 std::filesystem::directory_iterator(parentPath))
            {
                if (!std::filesystem::is_directory(path))
                {
                    continue;
                }

                const std::string& directoryName = path.path().filename();
                if (boost::starts_with(directoryName, busStr) &&
                    boost::ends_with(directoryName, addressHex))
                {
                    return; // already exported
                }
            }
        }
    }

    std::ofstream deviceFile(device);
    if (!deviceFile.good())
    {
        std::cerr << "Error writing " << device << "\n";
        return;
    }
    deviceFile << parameters;
    deviceFile.close();
    if (boost::ends_with(type, "Mux") && bus && address && channels)
    {
        linkMux(name, static_cast<size_t>(*bus), static_cast<size_t>(*address),
                *channels);
    }
}

// this is now deprecated
void createOverlay(const std::string& templatePath,
                   const nlohmann::json& configuration)
{
    std::ifstream templateFile(templatePath);

    if (!templateFile.is_open())
    {
        std::cerr << "createOverlay error opening " << templatePath << "\n";
        return;
    }
    std::stringstream buff;
    buff << templateFile.rdbuf();
    std::string templateStr = buff.str();
    std::string name = "unknown";
    std::string type = configuration["Type"];
    for (auto keyPair = configuration.begin(); keyPair != configuration.end();
         keyPair++)
    {
        std::string subsituteString;

        // device tree symbols are in decimal
        if (keyPair.key() == "Bus" &&
            keyPair.value().type() == nlohmann::json::value_t::string)
        {
            long unsigned int dec =
                std::stoul(keyPair.value().get<std::string>(), nullptr, 16);
            subsituteString = std::to_string(dec);
        }
        else if (keyPair.key() == "Name" &&
                 keyPair.value().type() == nlohmann::json::value_t::string)
        {
            subsituteString = std::regex_replace(
                keyPair.value().get<std::string>(), ILLEGAL_NAME_REGEX, "_");
            name = subsituteString;
        }
        else if (keyPair.key() == "Address")
        {
            if (keyPair.value().type() == nlohmann::json::value_t::string)
            {
                subsituteString = keyPair.value().get<std::string>();
                subsituteString.erase(
                    0, subsituteString.find_first_not_of(HEX_FORMAT_STR));
            }
            else
            {
                std::ostringstream hex;
                hex << std::hex << keyPair.value().get<unsigned int>();
                subsituteString = hex.str();
            }
        }
        else
        {
            subsituteString = jsonToString(keyPair.value());
        }
        boost::replace_all(templateStr, TEMPLATE_CHAR + keyPair.key(),
                           subsituteString);
    }
    // todo: this is a lame way to fill in platform, but we only
    // care about ast2500 right now
    boost::replace_all(templateStr, TEMPLATE_CHAR + std::string("Platform"),
                       PLATFORM);
    std::string dtsFilename =
        std::string(OUTPUT_DIR) + "/" + name + "_" + type + ".dts";
    std::string dtboFilename =
        std::string(OUTPUT_DIR) + "/" + name + "_" + type + ".dtbo";

    std::ofstream out(dtsFilename);
    if (!out.is_open())
    {
        std::cerr << "createOverlay error opening " << dtsFilename << "\n";
        return;
    }
    out << templateStr;
    out.close();

    // compile dtbo and load overlay
    boost::process::child c1(DTC, "-@", "-q", "-I", "dts", "-O", "dtb", "-o",
                             dtboFilename, dtsFilename);
    c1.wait();
    if (c1.exit_code())
    {
        std::cerr << "DTC error with file " << dtsFilename << "\n";
        return;
    }
    boost::process::child c2(DT_OVERLAY, "-d", OUTPUT_DIR, name + "_" + type);
    c2.wait();
    if (c2.exit_code())
    {
        std::cerr << "DTOverlay error with file " << dtboFilename << "\n";
        return;
    }
    auto findForceProbe = FORCE_PROBES.find(type);
    if (findForceProbe != FORCE_PROBES.end())
    {
        forceProbe(findForceProbe->second);
    }
}

bool loadOverlays(const nlohmann::json& systemConfiguration)
{

    std::vector<std::filesystem::path> paths;
    if (!findFiles(std::filesystem::path(TEMPLATE_DIR), R"(.*\.template)",
                   paths))
    {
        std::cerr << "Unable to find any template files in " << TEMPLATE_DIR
                  << "\n";
        return false;
    }

    std::filesystem::create_directory(OUTPUT_DIR);
    for (auto entity = systemConfiguration.begin();
         entity != systemConfiguration.end(); entity++)
    {
        auto findExposes = entity.value().find("Exposes");
        if (findExposes == entity.value().end() ||
            findExposes->type() != nlohmann::json::value_t::array)
        {
            continue;
        }

        for (auto& configuration : *findExposes)
        {
            auto findStatus = configuration.find("Status");
            // status missing is assumed to be 'okay'
            if (findStatus != configuration.end() && *findStatus == "disabled")
            {
                continue;
            }
            auto findType = configuration.find("Type");
            if (findType == configuration.end() ||
                findType->type() != nlohmann::json::value_t::string)
            {
                continue;
            }
            std::string type = findType.value().get<std::string>();
#if OVERLAYS

            std::string typeFile = type + std::string(".template");
            for (const auto& path : paths)
            {
                if (path.filename() != typeFile)
                {
                    continue;
                }
                createOverlay(path.string(), configuration);
                break;
            }
#endif
            auto device = devices::exportTemplates.find(type.c_str());
            if (device != devices::exportTemplates.end())
            {
                exportDevice(type, device->second, configuration);
                continue;
            }

            // Because many devices are intentionally not exportable,
            // this error message is not printed in all situations.
            // If wondering why your device not appearing, add your type to
            // the exportTemplates array in the devices.hpp file.
            if constexpr (DEBUG)
            {
                std::cerr << "Device type " << type
                          << " not found in export map whitelist\n";
            }
        }
    }

    return true;
}
