/*
// 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 "srvcfg_manager.hpp"

#include <boost/asio/detached.hpp>
#include <boost/asio/spawn.hpp>

#ifdef USB_CODE_UPDATE
#include <cereal/archives/json.hpp>
#include <cereal/types/tuple.hpp>
#include <cereal/types/unordered_map.hpp>

#include <cstdio>
#endif

#include <fstream>
#include <regex>

extern std::unique_ptr<boost::asio::steady_timer> timer;
extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
    srvMgrObjects;
static bool updateInProgress = false;

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/";

#ifdef USB_CODE_UPDATE
static constexpr const char* usbCodeUpdateStateFilePath =
    "/var/lib/srvcfg_manager";
static constexpr const char* usbCodeUpdateStateFile =
    "/var/lib/srvcfg_manager/usb-code-update-state";
static constexpr const char* emptyUsbCodeUpdateRulesFile =
    "/etc/udev/rules.d/70-bmc-usb.rules";

using UsbCodeUpdateStateMap = std::unordered_map<std::string, bool>;

void ServiceConfig::setUSBCodeUpdateState(const bool& state)
{
    // Enable usb code update
    if (state)
    {
        if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
        {
            lg2::info("Enable usb code update");
            std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
        }
        return;
    }

    // Disable usb code update
    if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
    {
        std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
    }
    std::error_code ec;
    std::filesystem::create_symlink("/dev/null", emptyUsbCodeUpdateRulesFile,
                                    ec);
    if (ec)
    {
        lg2::error("Disable usb code update failed");
        return;
    }
    lg2::info("Disable usb code update");
}

void ServiceConfig::saveUSBCodeUpdateStateToFile(const bool& maskedState,
                                                 const bool& enabledState)
{
    if (!std::filesystem::exists(usbCodeUpdateStateFilePath))
    {
        std::filesystem::create_directories(usbCodeUpdateStateFilePath);
    }

    UsbCodeUpdateStateMap usbCodeUpdateState;
    usbCodeUpdateState[srvCfgPropMasked] = maskedState;
    usbCodeUpdateState[srvCfgPropEnabled] = enabledState;

    std::ofstream file(usbCodeUpdateStateFile, std::ios::out);
    cereal::JSONOutputArchive archive(file);
    archive(CEREAL_NVP(usbCodeUpdateState));
}

void ServiceConfig::getUSBCodeUpdateStateFromFile()
{
    if (!std::filesystem::exists(usbCodeUpdateStateFile))
    {
        lg2::info("usb-code-update-state file does not exist");

        unitMaskedState = false;
        unitEnabledState = true;
        unitRunningState = true;
        setUSBCodeUpdateState(unitEnabledState);
        return;
    }

    std::ifstream file(usbCodeUpdateStateFile);
    cereal::JSONInputArchive archive(file);
    UsbCodeUpdateStateMap usbCodeUpdateState;
    archive(usbCodeUpdateState);

    auto iterMask = usbCodeUpdateState.find(srvCfgPropMasked);
    if (iterMask != usbCodeUpdateState.end())
    {
        unitMaskedState = iterMask->second;
        if (unitMaskedState)
        {
            unitEnabledState = !unitMaskedState;
            unitRunningState = !unitMaskedState;
            setUSBCodeUpdateState(unitEnabledState);
            return;
        }

        auto iterEnable = usbCodeUpdateState.find(srvCfgPropEnabled);
        if (iterEnable != usbCodeUpdateState.end())
        {
            unitEnabledState = iterEnable->second;
            unitRunningState = iterEnable->second;
            setUSBCodeUpdateState(unitEnabledState);
        }
    }
}
#endif

void ServiceConfig::updateSocketProperties(
    const boost::container::flat_map<std::string, VariantType>& propertyMap)
{
    auto listenIt = propertyMap.find("Listen");
    if (listenIt != propertyMap.end())
    {
        auto listenVal =
            std::get<std::vector<std::tuple<std::string, std::string>>>(
                listenIt->second);
        if (listenVal.size())
        {
            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;
            if (sockAttrIface && sockAttrIface->is_initialized())
            {
                internalSet = true;
                sockAttrIface->set_property(sockAttrPropPort, portNum);
                internalSet = false;
            }
        }
    }
}

void ServiceConfig::updateServiceProperties(
    const boost::container::flat_map<std::string, VariantType>& propertyMap)
{
    auto stateIt = propertyMap.find("UnitFileState");
    if (stateIt != propertyMap.end())
    {
        stateValue = std::get<std::string>(stateIt->second);
        unitEnabledState = unitMaskedState = false;
        if (stateValue == stateMasked)
        {
            unitMaskedState = true;
        }
        else if (stateValue == stateEnabled)
        {
            unitEnabledState = true;
        }
        if (srvCfgIface && srvCfgIface->is_initialized())
        {
            internalSet = true;
            srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState);
            srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
            internalSet = false;
        }
    }
    auto subStateIt = propertyMap.find("SubState");
    if (subStateIt != propertyMap.end())
    {
        subStateValue = std::get<std::string>(subStateIt->second);
        if (subStateValue == subStateRunning ||
            subStateValue == subStateListening)
        {
            unitRunningState = true;
        }
        if (srvCfgIface && srvCfgIface->is_initialized())
        {
            internalSet = true;
            srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
            internalSet = false;
        }
    }

#ifdef USB_CODE_UPDATE
    if (baseUnitName == usbCodeUpdateUnitName)
    {
        getUSBCodeUpdateStateFromFile();
    }
#endif
}

void ServiceConfig::queryAndUpdateProperties()
{
    std::string objectPath =
        isSocketActivatedService ? socketObjectPath : serviceObjectPath;
    if (objectPath.empty())
    {
        return;
    }

    conn->async_method_call(
        [this](boost::system::error_code ec,
               const boost::container::flat_map<std::string, VariantType>&
                   propertyMap) {
            if (ec)
            {
                lg2::error(
                    "async_method_call error: Failed to service unit properties: {EC}",
                    "EC", ec.value());
                return;
            }
            try
            {
                updateServiceProperties(propertyMap);
                if (!socketObjectPath.empty())
                {
                    conn->async_method_call(
                        [this](boost::system::error_code ec,
                               const boost::container::flat_map<
                                   std::string, VariantType>& propertyMap) {
                            if (ec)
                            {
                                lg2::error(
                                    "async_method_call error: Failed to get all property: {EC}",
                                    "EC", ec.value());
                                return;
                            }
                            try
                            {
                                updateSocketProperties(propertyMap);
                                if (!srvCfgIface)
                                {
                                    registerProperties();
                                }
                            }
                            catch (const std::exception& e)
                            {
                                lg2::error(
                                    "Exception in getting socket properties: {ERROR}",
                                    "ERROR", e);
                                return;
                            }
                        },
                        sysdService, socketObjectPath, dBusPropIntf,
                        dBusGetAllMethod, sysdSocketIntf);
                }
                else if (!srvCfgIface)
                {
                    registerProperties();
                }
            }
            catch (const std::exception& e)
            {
                lg2::error("Exception in getting socket properties: {ERROR}",
                           "ERROR", e);
                return;
            }
        },
        sysdService, objectPath, dBusPropIntf, dBusGetAllMethod, sysdUnitIntf);
    return;
}

void ServiceConfig::createSocketOverrideConf()
{
    if (!socketObjectPath.empty())
    {
        std::string socketUnitName(instantiatedUnitName + ".socket");
        /// Check override socket directory exist, if not create it.
        std::filesystem::path ovrUnitFileDir(systemdOverrideUnitBasePath);
        ovrUnitFileDir += socketUnitName;
        ovrUnitFileDir += ".d";
        if (!std::filesystem::exists(ovrUnitFileDir))
        {
            if (!std::filesystem::create_directories(ovrUnitFileDir))
            {
                lg2::error("Unable to create the {DIR} directory.", "DIR",
                           ovrUnitFileDir);
                phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
                                            Common::Error::InternalFailure>();
            }
        }
        overrideConfDir = std::string(ovrUnitFileDir);
    }
}

ServiceConfig::ServiceConfig(
    sdbusplus::asio::object_server& srv_,
    std::shared_ptr<sdbusplus::asio::connection>& conn_,
    const std::string& objPath_, const std::string& baseUnitName_,
    const std::string& instanceName_, const std::string& serviceObjPath_,
    const std::string& socketObjPath_) :
    conn(conn_), server(srv_), objPath(objPath_), baseUnitName(baseUnitName_),
    instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
    socketObjectPath(socketObjPath_)
{
    isSocketActivatedService = serviceObjectPath.empty();
    instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
    updatedFlag = 0;
    queryAndUpdateProperties();
    return;
}

std::string ServiceConfig::getSocketUnitName()
{
    return instantiatedUnitName + ".socket";
}

std::string ServiceConfig::getServiceUnitName()
{
    return instantiatedUnitName + ".service";
}

bool ServiceConfig::isMaskedOut()
{
    // return true  if state is masked & no request to update the maskedState
    return (
        stateValue == "masked" &&
        !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
}

void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
{
    if (!updatedFlag || isMaskedOut())
    {
        // No updates / masked - Just return.
        return;
    }
    lg2::info("Applying new settings: {OBJPATH}", "OBJPATH", objPath);
    if (subStateValue == subStateRunning || subStateValue == subStateListening)
    {
        if (!socketObjectPath.empty())
        {
            systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
        }
        if (!isSocketActivatedService)
        {
            systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
        }
        else
        {
            // For socket-activated service, each connection will spawn a
            // service instance from template. Need to find all spawned service
            // `<unitName>@<attribute>.service` and stop them through the
            // systemdUnitAction method
            boost::system::error_code ec;
            auto listUnits =
                conn->yield_method_call<std::vector<ListUnitsType>>(
                    yield, ec, sysdService, sysdObjPath, sysdMgrIntf,
                    "ListUnits");

            checkAndThrowInternalFailure(
                ec, "yield_method_call error: ListUnits failed");

            for (const auto& unit : listUnits)
            {
                const auto& service =
                    std::get<static_cast<int>(ListUnitElements::name)>(unit);
                const auto& status =
                    std::get<static_cast<int>(ListUnitElements::subState)>(
                        unit);
                if (service.find(baseUnitName + "@") != std::string::npos &&
                    service.find(".service") != std::string::npos &&
                    status == subStateRunning)
                {
                    systemdUnitAction(conn, yield, service, sysdStopUnit);
                }
            }
        }
    }

    if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
    {
        createSocketOverrideConf();
        // Create override config file and write data.
        std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
        std::string tmpFile{ovrCfgFile + "_tmp"};
        std::ofstream cfgFile(tmpFile, std::ios::out);
        if (!cfgFile.good())
        {
            lg2::error("Failed to open the {TMPFILE} file.", "TMPFILE",
                       tmpFile);
            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";
        cfgFile.close();

        if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
        {
            lg2::error("Failed to rename {TMPFILE} file as {OVERCFGFILE} file.",
                       "TMPFILE", tmpFile, "OVERCFGFILE", ovrCfgFile);
            std::remove(tmpFile.c_str());
            phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
                                        Error::InternalFailure>();
        }
    }

    if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
                       (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
    {
        std::vector<std::string> unitFiles;
        if (socketObjectPath.empty())
        {
            unitFiles = {getServiceUnitName()};
        }
        else if (serviceObjectPath.empty())
        {
            unitFiles = {getSocketUnitName()};
        }
        else
        {
            unitFiles = {getSocketUnitName(), getServiceUnitName()};
        }
        systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
                                    unitMaskedState, unitEnabledState);
    }
    return;
}
void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
{
    if (!updatedFlag || isMaskedOut())
    {
        // No updates. Just return.
        return;
    }

    if (unitRunningState)
    {
        if (!socketObjectPath.empty())
        {
            systemdUnitAction(conn, yield, getSocketUnitName(),
                              sysdRestartUnit);
        }
        if (!serviceObjectPath.empty())
        {
            systemdUnitAction(conn, yield, getServiceUnitName(),
                              sysdRestartUnit);
        }
    }

    // Reset the flag
    updatedFlag = 0;

    lg2::info("Applied new settings: {OBJPATH}", "OBJPATH", objPath);

    queryAndUpdateProperties();
    return;
}

void ServiceConfig::startServiceRestartTimer()
{
    timer->expires_after(std::chrono::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)
        {
            lg2::error("async wait error: {EC}", "EC", ec.value());
            return;
        }
        updateInProgress = true;
        boost::asio::spawn(
            conn->get_io_context(),
            [this](boost::asio::yield_context yield) {
                // Stop and apply configuration for all objects
                for (auto& srvMgrObj : srvMgrObjects)
                {
                    auto& srvObj = srvMgrObj.second;
                    if (srvObj->updatedFlag)
                    {
                        srvObj->stopAndApplyUnitConfig(yield);
                    }
                }
                // Do system reload
                systemdDaemonReload(conn, yield);
                // restart unit config.
                for (auto& srvMgrObj : srvMgrObjects)
                {
                    auto& srvObj = srvMgrObj.second;
                    if (srvObj->updatedFlag)
                    {
                        srvObj->restartUnitConfig(yield);
                    }
                }
                updateInProgress = false;
            },
            boost::asio::detached);
    });
}

void ServiceConfig::registerProperties()
{
    srvCfgIface = server.add_interface(objPath, serviceConfigIntfName);

    if (!socketObjectPath.empty())
    {
        sockAttrIface = server.add_interface(objPath, sockAttrIntfName);
        sockAttrIface->register_property(
            sockAttrPropPort, portNum,
            [this](const uint16_t& req, uint16_t& res) {
                if (!internalSet)
                {
                    if (req == res)
                    {
                        return 1;
                    }
                    if (updateInProgress)
                    {
                        return 0;
                    }
                    portNum = req;
                    updatedFlag |=
                        (1 << static_cast<uint8_t>(UpdatedProp::port));
                    startServiceRestartTimer();
                }
                res = req;
                return 1;
            });
    }

    srvCfgIface->register_property(
        srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
            if (!internalSet)
            {
#ifdef USB_CODE_UPDATE
                if (baseUnitName == usbCodeUpdateUnitName)
                {
                    unitMaskedState = req;
                    unitEnabledState = !unitMaskedState;
                    unitRunningState = !unitMaskedState;
                    internalSet = true;
                    srvCfgIface->set_property(srvCfgPropEnabled,
                                              unitEnabledState);
                    srvCfgIface->set_property(srvCfgPropRunning,
                                              unitRunningState);
                    srvCfgIface->set_property(srvCfgPropMasked,
                                              unitMaskedState);
                    internalSet = false;
                    setUSBCodeUpdateState(unitEnabledState);
                    saveUSBCodeUpdateStateToFile(unitMaskedState,
                                                 unitEnabledState);
                    return 1;
                }
#endif
                if (req == res)
                {
                    return 1;
                }
                if (updateInProgress)
                {
                    return 0;
                }
                unitMaskedState = req;
                unitEnabledState = !unitMaskedState;
                unitRunningState = !unitMaskedState;
                updatedFlag |=
                    (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
                    (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
                    (1 << static_cast<uint8_t>(UpdatedProp::runningState));
                internalSet = true;
                srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
                srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
                internalSet = false;
                startServiceRestartTimer();
            }
            res = req;
            return 1;
        });

    srvCfgIface->register_property(
        srvCfgPropEnabled, unitEnabledState,
        [this](const bool& req, bool& res) {
            if (!internalSet)
            {
#ifdef USB_CODE_UPDATE
                if (baseUnitName == usbCodeUpdateUnitName)
                {
                    if (unitMaskedState)
                    { // block updating if masked
                        lg2::error("Invalid value specified");
                        return -EINVAL;
                    }
                    unitEnabledState = req;
                    unitRunningState = req;
                    internalSet = true;
                    srvCfgIface->set_property(srvCfgPropEnabled,
                                              unitEnabledState);
                    srvCfgIface->set_property(srvCfgPropRunning,
                                              unitRunningState);
                    internalSet = false;
                    setUSBCodeUpdateState(unitEnabledState);
                    saveUSBCodeUpdateStateToFile(unitMaskedState,
                                                 unitEnabledState);
                    res = req;
                    return 1;
                }
#endif
                if (req == res)
                {
                    return 1;
                }
                if (updateInProgress)
                {
                    return 0;
                }
                if (unitMaskedState)
                { // block updating if masked
                    lg2::error("Invalid value specified");
                    return -EINVAL;
                }
                unitEnabledState = req;
                updatedFlag |=
                    (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
                startServiceRestartTimer();
            }
            res = req;
            return 1;
        });

    srvCfgIface->register_property(
        srvCfgPropRunning, unitRunningState,
        [this](const bool& req, bool& res) {
            if (!internalSet)
            {
#ifdef USB_CODE_UPDATE
                if (baseUnitName == usbCodeUpdateUnitName)
                {
                    if (unitMaskedState)
                    { // block updating if masked
                        lg2::error("Invalid value specified");
                        return -EINVAL;
                    }
                    unitEnabledState = req;
                    unitRunningState = req;
                    internalSet = true;
                    srvCfgIface->set_property(srvCfgPropEnabled,
                                              unitEnabledState);
                    srvCfgIface->set_property(srvCfgPropRunning,
                                              unitRunningState);
                    internalSet = false;
                    setUSBCodeUpdateState(unitEnabledState);
                    saveUSBCodeUpdateStateToFile(unitMaskedState,
                                                 unitEnabledState);
                    res = req;
                    return 1;
                }
#endif
                if (req == res)
                {
                    return 1;
                }
                if (updateInProgress)
                {
                    return 0;
                }
                if (unitMaskedState)
                { // block updating if masked
                    lg2::error("Invalid value specified");
                    return -EINVAL;
                }
                unitRunningState = req;
                updatedFlag |=
                    (1 << static_cast<uint8_t>(UpdatedProp::runningState));
                startServiceRestartTimer();
            }
            res = req;
            return 1;
        });

    srvCfgIface->initialize();
    if (!socketObjectPath.empty())
    {
        sockAttrIface->initialize();
    }
    return;
}

} // namespace service
} // namespace phosphor
