/*
// 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_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::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>();
            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;
}
