/*
// 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 <fstream>
#include <regex>
#include "srvcfg_manager.hpp"

extern std::shared_ptr<boost::asio::deadline_timer> timer;
extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
    srvMgrObjects;

namespace phosphor
{
namespace service
{

static constexpr const char *overrideConfFileName = "override.conf";
static constexpr const size_t restartTimeout = 15; // seconds

static constexpr const char *systemd1UnitBasePath =
    "/org/freedesktop/systemd1/unit/";
static constexpr const char *systemdOverrideUnitBasePath =
    "/etc/systemd/system/";

void ServiceConfig::syncWithSystemD1Properties()
{
    // Read systemd1 socket/service property and load.
    conn->async_method_call(
        [this](boost::system::error_code ec,
               const sdbusplus::message::variant<
                   std::vector<std::tuple<std::string, std::string>>> &value) {
            if (ec)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "async_method_call error: Failed to get property");
                return;
            }

            try
            {
                auto listenVal = sdbusplus::message::variant_ns::get<
                    std::vector<std::tuple<std::string, std::string>>>(value);
                protocol = std::get<0>(listenVal[0]);
                std::string port = std::get<1>(listenVal[0]);
                auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1),
                                      nullptr, 10);
                if (tmp > std::numeric_limits<uint16_t>::max())
                {
                    throw std::out_of_range("Out of range");
                }
                portNum = tmp;
            }
            catch (const std::exception &e)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "Exception for port number",
                    phosphor::logging::entry("WHAT=%s", e.what()));
                return;
            }
            conn->async_method_call(
                [](boost::system::error_code ec) {
                    if (ec)
                    {
                        phosphor::logging::log<phosphor::logging::level::ERR>(
                            "async_method_call error: Failed to set property");
                        return;
                    }
                },
                serviceConfigSrvName, objPath.c_str(),
                "org.freedesktop.DBus.Properties", "Set", serviceConfigIntfName,
                "Port", sdbusplus::message::variant<uint16_t>(portNum));
        },
        "org.freedesktop.systemd1", sysDSockObjPath.c_str(),
        "org.freedesktop.DBus.Properties", "Get",
        "org.freedesktop.systemd1.Socket", "Listen");

    conn->async_method_call(
        [this](boost::system::error_code ec,
               const sdbusplus::message::variant<std::string> &pValue) {
            if (ec)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "async_method_call error: Failed to get property");
                return;
            }

            channelList.clear();
            std::istringstream stm(
                sdbusplus::message::variant_ns::get<std::string>(pValue));
            std::string token;
            while (std::getline(stm, token, ','))
            {
                channelList.push_back(token);
            }
            conn->async_method_call(
                [](boost::system::error_code ec) {
                    if (ec)
                    {
                        phosphor::logging::log<phosphor::logging::level::ERR>(
                            "async_method_call error: Failed to set property");
                        return;
                    }
                },
                serviceConfigSrvName, objPath.c_str(),
                "org.freedesktop.DBus.Properties", "Set", serviceConfigIntfName,
                "Channel",
                sdbusplus::message::variant<std::vector<std::string>>(
                    channelList));
        },
        "org.freedesktop.systemd1", sysDSockObjPath.c_str(),
        "org.freedesktop.DBus.Properties", "Get",
        "org.freedesktop.systemd1.Socket", "BindToDevice");

    std::string srvUnitName(sysDUnitName);
    if (srvUnitName == "dropbear")
    {
        // Dropbear service expects template arguments.
        srvUnitName.append("@");
    }
    srvUnitName.append(".service");
    conn->async_method_call(
        [this](boost::system::error_code ec, const std::string &pValue) {
            if (ec)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "async_method_call error: Failed to get property");
                return;
            }
            if ((pValue == "enabled") || (pValue == "static") ||
                (pValue == "unmasked"))
            {
                stateValue = "enabled";
            }
            else if ((pValue == "disabled") || (pValue == "masked"))
            {
                stateValue = "disabled";
            }
            conn->async_method_call(
                [](boost::system::error_code ec) {
                    if (ec)
                    {
                        phosphor::logging::log<phosphor::logging::level::ERR>(
                            "async_method_call error: Failed to set property");
                        return;
                    }
                },
                serviceConfigSrvName, objPath.c_str(),
                "org.freedesktop.DBus.Properties", "Set", serviceConfigIntfName,
                "State", sdbusplus::message::variant<std::string>(stateValue));
        },
        "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
        "org.freedesktop.systemd1.Manager", "GetUnitFileState", srvUnitName);

    return;
}

ServiceConfig::ServiceConfig(
    sdbusplus::asio::object_server &srv_,
    std::shared_ptr<sdbusplus::asio::connection> &conn_, std::string objPath_,
    std::string unitName) :
    server(srv_),
    conn(conn_), objPath(objPath_), sysDUnitName(unitName)
{
    std::string socketUnitName(sysDUnitName + ".socket");
    // .socket systemd service files are handled.
    // Regular .service only files are ignored.
    if (!checkSystemdUnitExist(socketUnitName))
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Unit doesn't exist.",
            phosphor::logging::entry("UNITNAME=%s", socketUnitName.c_str()));
        phosphor::logging::elog<
            sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
    }

    /// Check override socket directory exist, if not create it.
    std::experimental::filesystem::path ovrUnitFileDir(
        systemdOverrideUnitBasePath);
    ovrUnitFileDir += socketUnitName;
    ovrUnitFileDir += ".d";
    if (!std::experimental::filesystem::exists(ovrUnitFileDir))
    {
        if (!std::experimental::filesystem::create_directories(ovrUnitFileDir))
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Unable to create the directory.",
                phosphor::logging::entry("DIR=%s", ovrUnitFileDir.c_str()));
            phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
                                        Error::InternalFailure>();
        }
    }

    /* Store require info locally */
    unitSocketFilePath = std::string(ovrUnitFileDir);

    sysDSockObjPath = systemd1UnitBasePath;
    sysDSockObjPath.append(
        std::regex_replace(sysDUnitName, std::regex("-"), "_2d"));
    sysDSockObjPath.append("_2esocket");

    // Adds interface, object and Properties....
    registerProperties();

    syncWithSystemD1Properties();

    updatedFlag = 0;
    return;
}

void ServiceConfig::applySystemDServiceConfig()
{
    if (updatedFlag)
    {
        // No updates. Just return.
        return;
    }

    phosphor::logging::log<phosphor::logging::level::INFO>(
        "Applying new settings.",
        phosphor::logging::entry("OBJPATH=%s", objPath.c_str()));
    if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::channel)) |
                       (1 << static_cast<uint8_t>(UpdatedProp::port))))
    {
        // Create override config file and write data.
        std::string ovrCfgFile{unitSocketFilePath + "/" + overrideConfFileName};
        std::string tmpFile{ovrCfgFile + "_tmp"};
        std::ofstream cfgFile(tmpFile, std::ios::out);
        if (!cfgFile.good())
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Failed to open override.conf_tmp file");
            phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
                                        Error::InternalFailure>();
        }

        // Write the socket header
        cfgFile << "[Socket]\n";
        // Listen
        cfgFile << "Listen" << protocol << "="
                << "\n";
        cfgFile << "Listen" << protocol << "=" << portNum << "\n";
        // BindToDevice
        bool firstElement = true;
        cfgFile << "BindToDevice=";
        for (const auto &it : channelList)
        {
            if (firstElement)
            {
                cfgFile << it;
                firstElement = false;
            }
            else
            {
                cfgFile << "," << it;
            }
        }
        cfgFile.close();

        if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Failed to rename tmp file as override.conf");
            std::remove(tmpFile.c_str());
            phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
                                        Error::InternalFailure>();
        }
    }

    std::string socketUnitName(sysDUnitName + ".socket");
    std::string srvUnitName(sysDUnitName);
    if (srvUnitName == "dropbear")
    {
        // Dropbear service expects template arguments.
        // Todo: Unit action for service, fails with error
        // "missing the instance name". Needs to implement
        // getting all running instances and use it. This
        // impact runtime but works fine during reboot.
        srvUnitName.append("@");
    }
    srvUnitName.append(".service");
    // Stop the running service in below scenarios.
    // 1. State changed from "enabled" to "disabled"
    // 2. No change in state and existing stateValue is
    //    "enabled" and there is change in other properties.
    if (((stateValue == "disabled") &&
         (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::state)))) ||
        (!(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::state))) &&
         (stateValue == "enabled") && (updatedFlag)))
    {
        systemdUnitAction(conn, socketUnitName, "StopUnit");
        systemdUnitAction(conn, srvUnitName, "StopUnit");
    }

    if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::state)))
    {
        std::vector<std::string> unitFiles = {socketUnitName, srvUnitName};
        systemdUnitFilesStateChange(conn, unitFiles, stateValue);
    }

    // Perform daemon reload to read new settings
    systemdDaemonReload(conn);

    if (stateValue == "enabled")
    {
        // Restart the socket
        systemdUnitAction(conn, socketUnitName, "StartUnit");
    }

    // Reset the flag
    updatedFlag = 0;

    // All done. Lets reload the properties which are applied on systemd1.
    // TODO: We need to capture the service restart signal and reload data
    // inside the signal handler. So that we can update the service
    // properties modified, outside of this service as well.
    syncWithSystemD1Properties();

    return;
}

void ServiceConfig::startServiceRestartTimer()
{
    timer->expires_from_now(boost::posix_time::seconds(restartTimeout));
    timer->async_wait([this](const boost::system::error_code &ec) {
        if (ec == boost::asio::error::operation_aborted)
        {
            // Timer reset.
            return;
        }
        else if (ec)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "async wait error.");
            return;
        }
        for (auto &srvMgrObj : srvMgrObjects)
        {
            auto &srvObj = srvMgrObj.second;
            if (srvObj->updatedFlag)
            {
                srvObj->applySystemDServiceConfig();
            }
        }
    });
}

void ServiceConfig::registerProperties()
{
    std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
        server.add_interface(objPath, serviceConfigIntfName);

    iface->register_property(
        "Port", portNum, [this](const uint16_t &req, uint16_t &res) {
            if (req == res)
            {
                return 1;
            }
            portNum = req;
            updatedFlag |= (1 << static_cast<uint8_t>(UpdatedProp::port));
            startServiceRestartTimer();
            res = req;
            return 1;
        });

    iface->register_property(
        "Channel", channelList,
        [this](const std::vector<std::string> &req,
               std::vector<std::string> &res) {
            if (req == res)
            {
                return 1;
            }
            channelList.clear();
            std::copy(req.begin(), req.end(), back_inserter(channelList));

            updatedFlag |= (1 << static_cast<uint8_t>(UpdatedProp::channel));
            startServiceRestartTimer();
            res = req;
            return 1;
        });

    iface->register_property(
        "State", stateValue, [this](const std::string &req, std::string &res) {
            if (req == res)
            {
                return 1;
            }
            if ((req != "enabled") && (req != "disabled"))
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "Invalid value specified");
                return -EINVAL;
            }
            stateValue = req;
            updatedFlag |= (1 << static_cast<uint8_t>(UpdatedProp::state));
            startServiceRestartTimer();
            res = req;
            return 1;
        });

    iface->initialize();
    return;
}

} // namespace service
} // namespace phosphor
