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

#include "mdrv2.hpp"

#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>

static constexpr const char* biosActiveObjPath =
    "/xyz/openbmc_project/software/bios_active";
static constexpr const char* biosVersionIntf =
    "xyz.openbmc_project.Software.Version";
static constexpr const char* biosVersionProp = "Version";

namespace phosphor
{
namespace smbios
{

std::string System::uuid(std::string value)
{
    uint8_t* dataIn = storage;
    dataIn = getSMBIOSTypePtr(dataIn, systemType);
    if (dataIn != nullptr)
    {
        auto systemInfo = reinterpret_cast<struct SystemInfo*>(dataIn);
        std::stringstream stream;
        stream << std::setfill('0') << std::hex;
        stream << std::setw(8) << systemInfo->uuid.timeLow;
        stream << "-";
        stream << std::setw(4) << systemInfo->uuid.timeMid;
        stream << "-";
        stream << std::setw(4) << systemInfo->uuid.timeHiAndVer;
        stream << "-";
        stream << std::setw(2) << static_cast<int>(systemInfo->uuid.clockSeqHi);
        stream << std::setw(2)
               << static_cast<int>(systemInfo->uuid.clockSeqLow);
        stream << "-";
        static_assert(sizeof(systemInfo->uuid.node) == 6);
        stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[0]);
        stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[1]);
        stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[2]);
        stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[3]);
        stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[4]);
        stream << std::setw(2) << static_cast<int>(systemInfo->uuid.node[5]);

        return sdbusplus::server::xyz::openbmc_project::common::UUID::uuid(
            stream.str());
    }

    return sdbusplus::server::xyz::openbmc_project::common::UUID::uuid(
        "00000000-0000-0000-0000-000000000000");
}

static std::string getService(sdbusplus::bus_t& bus,
                              const std::string& objectPath,
                              const std::string& interface)
{
    auto method = bus.new_method_call("xyz.openbmc_project.ObjectMapper",
                                      "/xyz/openbmc_project/object_mapper",
                                      "xyz.openbmc_project.ObjectMapper",
                                      "GetObject");

    method.append(objectPath);
    method.append(std::vector<std::string>({interface}));

    std::vector<std::pair<std::string, std::vector<std::string>>> response;

    try
    {
        auto reply = bus.call(method);
        reply.read(response);
    }
    catch (const sdbusplus::exception_t& e)
    {
        lg2::error("Error in mapper method call - {ERROR}, SERVICE - "
                   "{SERVICE}, PATH - {PATH}",
                   "ERROR", e.what(), "SERVICE", objectPath.c_str(), "PATH",
                   interface.c_str());

        return std::string{};
    }

    return response[0].first;
}

static void setProperty(sdbusplus::bus_t& bus, const std::string& objectPath,
                        const std::string& interface,
                        const std::string& propertyName,
                        const std::string& value)
{
    auto service = getService(bus, objectPath, interface);
    if (service.empty())
    {
        return;
    }

    auto method = bus.new_method_call(service.c_str(), objectPath.c_str(),
                                      "org.freedesktop.DBus.Properties", "Set");
    method.append(interface.c_str(), propertyName.c_str(),
                  std::variant<std::string>{value});

    bus.call_noreply(method);
}

std::string System::version(std::string value)
{
    std::string result = "No BIOS Version";
    uint8_t* dataIn = storage;
    dataIn = getSMBIOSTypePtr(dataIn, biosType);
    if (dataIn != nullptr)
    {
        auto biosInfo = reinterpret_cast<struct BIOSInfo*>(dataIn);
        uint8_t biosVerByte = biosInfo->biosVersion;
        std::string tempS = positionToString(biosInfo->biosVersion,
                                             biosInfo->length, dataIn);
        if (std::find_if(tempS.begin(), tempS.end(),
                         [](char ch) { return !isprint(ch); }) != tempS.end())
        {
            std::ofstream smbiosFile(mdrType2File, std::ios_base::trunc);
            if (!smbiosFile.good())
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "Open MDRV2 table file failure");
                return result;
            }
            smbiosFile.clear();
            smbiosFile.close();
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Find non-print char, delete the broken MDRV2 table file!");
            return sdbusplus::server::xyz::openbmc_project::inventory::
                decorator::Revision::version(result);
        }
        result = tempS;

        setProperty(bus, biosActiveObjPath, biosVersionIntf, biosVersionProp,
                    result);
    }
    lg2::info("VERSION INFO - BIOS - {VER}", "VER", result);

    return sdbusplus::server::xyz::openbmc_project::inventory::decorator::
        Revision::version(result);
}

} // namespace smbios
} // namespace phosphor
