/*
// 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.
*/

#pragma once

#include <ipmid/api-types.hpp>
#include <ipmid/utils.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/message.hpp>
#include <sdbusplus/timer.hpp>

#include <vector>

#define FAN_SENSOR_NOT_PRESENT (0 << 0)
#define FAN_SENSOR_PRESENT (1 << 0)
#define FAN_NOT_PRESENT (0 << 1)
#define FAN_PRESENT (1 << 1)

namespace ipmi
{

// TODO: Service names may change. Worth to consider dynamic detection.
static constexpr const char* fanService = "xyz.openbmc_project.FanSensor";
static constexpr const char* buttonService =
    "xyz.openbmc_project.Chassis.Buttons";
static constexpr const char* ledServicePrefix =
    "xyz.openbmc_project.LED.Controller.";

static constexpr const char* ledPathPrefix =
    "/xyz/openbmc_project/led/physical/";
static constexpr const char* fanPwmPath =
    "/xyz/openbmc_project/sensors/fan_pwm/";
static constexpr const char* fanTachBasePath =
    "/xyz/openbmc_project/sensors/fan_tach/";

static constexpr const char* fanIntf = "xyz.openbmc_project.Sensor.Value";
static constexpr const char* buttonIntf = "xyz.openbmc_project.Chassis.Buttons";
static constexpr const char* ledIntf = "xyz.openbmc_project.Led.Physical";

static constexpr const char* intrusionService =
    "xyz.openbmc_project.IntrusionSensor";
static constexpr const char* intrusionPath =
    "/xyz/openbmc_project/Intrusion/Chassis_Intrusion";
static constexpr const char* intrusionIntf =
    "xyz.openbmc_project.Chassis.Intrusion";

static constexpr const char* busPropertyIntf =
    "org.freedesktop.DBus.Properties";
static constexpr const char* ledStateStr =
    "xyz.openbmc_project.Led.Physical.Action."; // Comes with postfix Off/On

static constexpr const char* specialModeService =
    "xyz.openbmc_project.SpecialMode";
static constexpr const char* specialModeObjPath =
    "/xyz/openbmc_project/security/special_mode";
static constexpr const char* specialModeIntf =
    "xyz.openbmc_project.Security.SpecialMode";

enum class SpecialMode : uint8_t
{
    none = 0,
    mfg = 1,
#ifdef BMC_VALIDATION_UNSECURE_FEATURE
    valUnsecure = 2
#endif
};

enum class SmActionGet : uint8_t
{
    sample = 0,
    ignore = 1,
    revert = 2
};

enum class SmActionSet : uint8_t
{
    forceDeasserted = 0,
    forceAsserted = 1,
    revert = 2
};

enum class SmSignalGet : uint8_t
{
    smPowerButton = 0,
    smResetButton = 1,
    smSleepButton,
    smNMIButton = 3,
    smChassisIntrusion = 4,
    smPowerGood,
    smPowerRequestGet,
    smSleepRequestGet,
    smFrbTimerHaltGet,
    smForceUpdate,
    smRingIndication,
    smCarrierDetect,
    smIdentifyButton = 0xc,
    smFanPwmGet = 0xd,
    smSignalReserved,
    smFanTachometerGet = 0xf,
    smNcsiDiag = 0x10,
    smGetSignalMax
};

enum class SmSignalSet : uint8_t
{
    smPowerLed = 0,
    smPowerFaultLed,
    smClusterLed,
    smDiskFaultLed,
    smCoolingFaultLed,
    smFanPowerSpeed = 5,
    smPowerRequestSet,
    smSleepRequestSet,
    smAcpiSci,
    smSpeaker,
    smFanPackFaultLed,
    smCpuFailLed,
    smDimmFailLed,
    smIdentifyLed,
    smHddLed,
    smSystemReadyLed,
    smLcdBacklight = 0x10,
    smSetSignalMax
};

/** @enum IntrusionStatus
.*
 *  Intrusion Status
 */
enum class IntrusionStatus : uint8_t
{
    normal = 0,
    hardwareIntrusion,
    tamperingDetected
};

enum SupportedFeatureControls : uint8_t
{
    mctp = 0,
    pcieScan,
};

enum SupportedFeatureActions : uint8_t
{
    stop = 0,
    start,
    disable,
    enable,
};

enum SupportedMCTPBindings : uint8_t
{
    mctpPCIe = 0,
    mctpSMBusHSBP,
    mctpSMBusPCIeSlot
};

struct SetSmSignalReq
{
    SmSignalSet Signal;
    uint8_t Instance;
    SmActionSet Action;
    uint8_t Value;
};

class LedProperty
{
    SmSignalSet signal;
    std::string name;
    std::string prevState;
    std::string currentState;
    bool isLocked;

  public:
    LedProperty(SmSignalSet signal_, std::string name_) :
        signal(signal_), name(name_), prevState(""), isLocked(false)
    {}

    LedProperty() = delete;

    SmSignalSet getSignal() const
    {
        return signal;
    }

    void setLock(const bool& lock)
    {
        isLocked = lock;
    }
    void setPrevState(const std::string& state)
    {
        prevState = state;
    }
    void setCurrState(const std::string& state)
    {
        currentState = state;
    }
    std::string getCurrState() const
    {
        return currentState;
    }
    bool getLock() const
    {
        return isLocked;
    }
    std::string getPrevState() const
    {
        return prevState;
    }
    std::string getName() const
    {
        return name;
    }
};

/** @class Manufacturing
 *
 *  @brief Implemet commands to support Manufacturing Test Mode.
 */
class Manufacturing
{
    std::string path;
    std::string gpioPaths[(uint8_t)SmSignalGet::smGetSignalMax];
    std::vector<LedProperty> ledPropertyList;
    void initData();

  public:
    Manufacturing();

    ipmi_return_codes detectAccessLvl(ipmi_request_t request,
                                      ipmi_data_len_t req_len);

    LedProperty* findLedProperty(const SmSignalSet& signal)
    {
        auto it = std::find_if(ledPropertyList.begin(), ledPropertyList.end(),
                               [&signal](const LedProperty& led) {
            return led.getSignal() == signal;
        });
        if (it != ledPropertyList.end())
        {
            return &(*it);
        }
        return nullptr;
    }

    std::string getLedPropertyName(const SmSignalSet signal)
    {
        LedProperty* led = findLedProperty(signal);
        if (led != nullptr)
        {
            return led->getName();
        }
        else
        {
            return "";
        }
    }

    int8_t getProperty(const std::string& service, const std::string& path,
                       const std::string& interface,
                       const std::string& propertyName, ipmi::Value* value);
    int8_t setProperty(const std::string& service, const std::string& path,
                       const std::string& interface,
                       const std::string& propertyName, ipmi::Value value);
    int8_t disablePidControlService(const bool disable);

    void revertTimerHandler();

    SpecialMode getMfgMode(void)
    {
        ipmi::Value mode;
        if (getProperty(specialModeService, specialModeObjPath, specialModeIntf,
                        "SpecialMode", &mode) != 0)
        {
            return SpecialMode::none;
        }
        if (std::get<std::string>(mode) ==
            "xyz.openbmc_project.Control.Security.SpecialMode.Modes."
            "Manufacturing")
        {
            return SpecialMode::mfg;
        }
#ifdef BMC_VALIDATION_UNSECURE_FEATURE
        if (std::get<std::string>(mode) ==
            "xyz.openbmc_project.Control.Security.SpecialMode.Modes."
            "ValidationUnsecure")
        {
            return SpecialMode::valUnsecure;
        }
#endif
        return SpecialMode::none;
    }

    bool revertFanPWM = false;
    bool revertLedCallback = false;
    phosphor::Timer revertTimer;
    int mtmTestBeepFd = -1;
};

} // namespace ipmi
