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