/*
// 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.
*/
/// \file overlay.cpp

#include "overlay.hpp"

#include "utils.hpp"
#include "devices.hpp"

#include <boost/algorithm/string/predicate.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <boost/process/child.hpp>
#include <nlohmann/json.hpp>

#include <filesystem>
#include <iomanip>
#include <iostream>
#include <regex>
#include <string>

constexpr const char* outputDir = "/tmp/overlays";
constexpr const char* templateChar = "$";
constexpr const char* i2CDevsDir = "/sys/bus/i2c/devices";
constexpr const char* muxSymlinkDir = "/dev/i2c-mux";

constexpr const bool debug = false;

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

// 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>();
    }
    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 muxSymlinkDirPath(muxSymlinkDir);
    std::filesystem::create_directory(muxSymlinkDirPath, ec);
    // ignore error codes here if the directory already exists
    ec.clear();
    std::filesystem::path linkDir = muxSymlinkDirPath / muxName;
    std::filesystem::create_directory(linkDir, ec);

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

    std::filesystem::path devDir(i2CDevsDir);
    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";
        }
    }
}

static int deleteDevice(const std::string& devicePath,
                        const std::shared_ptr<uint64_t>& address,
                        const std::string& destructor)
{
    if (!address)
    {
        return -1;
    }
    std::filesystem::path deviceDestructor(devicePath);
    deviceDestructor /= destructor;
    std::ofstream deviceFile(deviceDestructor);
    if (!deviceFile.good())
    {
        std::cerr << "Error writing " << deviceDestructor << "\n";
        return -1;
    }
    deviceFile << std::to_string(*address);
    deviceFile.close();
    return 0;
}

static int createDevice(const std::string& devicePath,
                        const std::string& parameters,
                        const std::string& constructor)
{
    std::filesystem::path deviceConstructor(devicePath);
    deviceConstructor /= constructor;
    std::ofstream deviceFile(deviceConstructor);
    if (!deviceFile.good())
    {
        std::cerr << "Error writing " << deviceConstructor << "\n";
        return -1;
    }
    deviceFile << parameters;
    deviceFile.close();

    return 0;
}

static bool deviceIsCreated(const std::string& devicePath,
                            const std::shared_ptr<uint64_t>& bus,
                            const std::shared_ptr<uint64_t>& address,
                            const bool retrying)
{
    if (!bus || !address)
    {
        return false;
    }

    std::ostringstream hex;
    hex << std::hex << std::setw(4) << std::setfill('0') << *address;
    std::string addressHex = hex.str();
    std::string busStr = std::to_string(*bus);

    std::error_code ec;
    auto path = std::filesystem::recursive_directory_iterator(devicePath, ec);
    if (ec)
    {
        std::cerr << "Unable to open path " << devicePath << "\n";
        return false;
    }
    for (; path != std::filesystem::recursive_directory_iterator(); path++)
    {
        if (!std::filesystem::is_directory(*path))
        {
            continue;
        }

        const std::string directoryName = path->path().filename();
        std::string name = busStr;
        name += "-";
        name += addressHex;
        if (directoryName == name)
        {
            // The first time the BMC boots the kernel has creates a
            // filesystem enumerating the I2C devices. The I2C device has not
            // been initialized for use. This requires a call to a device
            // node, such as "new_device". The first pass through this
            // function is only confirming the filesystem contains the device
            // entry of interest (i.e. i2c4-0050).
            //
            // An upper level function performs the device creation
            // action. This action may fail. The device driver (dd) used to
            // create the I2C filesystem substructure eats any error codes,
            // and always returns 0. This is by design. It is also possible
            // for the new_device action to fail because the device is not
            // actually in the system, i.e. optional equipment.
            //
            // The 'retrying' pass of this function is used to confirm the
            // 'dd' device driver succeeded. Success is measured by finding
            // the 'hwmon' subdirectory in the filesystem. The first attempt
            // is delayed by an arbitrary amount, in order to permit the
            // kernel time to create the filesystem entries. The upper level
            // function determines the number of times to retry calling this
            // function.
            if (retrying)
            {
                std::error_code ec;
                std::filesystem::path hwmonDir(devicePath);
                hwmonDir /= directoryName;
                hwmonDir /= "hwmon";
                return std::filesystem::is_directory(hwmonDir, ec);
            }
            return true;
        }
        path.disable_recursion_pending();
    }
    return false;
}

static int buildDevice(const std::string& devicePath,
                       const std::string& parameters,
                       const std::shared_ptr<uint64_t>& bus,
                       const std::shared_ptr<uint64_t>& address,
                       const std::string& constructor,
                       const std::string& destructor, const bool createsHWMon,
                       const size_t retries = 5)
{
    bool tryAgain = false;
    if (!retries)
    {
        return -1;
    }

    if (!deviceIsCreated(devicePath, bus, address, false))
    {
        createDevice(devicePath, parameters, constructor);
        tryAgain = true;
    }
    else if (createsHWMon && !deviceIsCreated(devicePath, bus, address, true))
    {
        // device is present, hwmon subdir missing
        deleteDevice(devicePath, address, destructor);
        tryAgain = true;
    }

    if (tryAgain)
    {
        std::shared_ptr<boost::asio::steady_timer> createTimer =
            std::make_shared<boost::asio::steady_timer>(io);
        createTimer->expires_after(std::chrono::milliseconds(500));
        createTimer->async_wait([createTimer, devicePath, parameters, bus,
                                 address, constructor, destructor, createsHWMon,
                                 retries](const boost::system::error_code& ec) {
            if (ec)
            {
                std::cerr << "Timer error: " << ec << "\n";
                return -2;
            }
            return buildDevice(devicePath, parameters, bus, address,
                               constructor, destructor, createsHWMon,
                               retries - 1);
        });
    }
    return 0;
}

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

    std::string parameters = exportTemplate.parameters;
    std::string devicePath = exportTemplate.devicePath;
    std::string constructor = exportTemplate.add;
    std::string destructor = exportTemplate.remove;
    bool createsHWMon = exportTemplate.createsHWMon;
    std::string name = "unknown";
    std::shared_ptr<uint64_t> bus = nullptr;
    std::shared_ptr<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>(), illegalNameRegex, "_");
            name = subsituteString;
        }
        else
        {
            subsituteString = jsonToString(keyPair.value());
        }

        if (keyPair.key() == "Bus")
        {
            bus = std::make_shared<uint64_t>(
                *keyPair.value().get_ptr<const uint64_t*>());
        }
        else if (keyPair.key() == "Address")
        {
            address = std::make_shared<uint64_t>(
                *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, templateChar + keyPair.key(),
                           subsituteString);
        boost::replace_all(devicePath, templateChar + keyPair.key(),
                           subsituteString);
    }

    int err = buildDevice(devicePath, parameters, bus, address, constructor,
                          destructor, createsHWMon);

    if (!err && boost::ends_with(type, "Mux") && bus && address && channels)
    {
        linkMux(name, static_cast<size_t>(*bus), static_cast<size_t>(*address),
                *channels);
    }
}

bool loadOverlays(const nlohmann::json& systemConfiguration)
{
    std::filesystem::create_directory(outputDir);
    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;
}
