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

#include <fcntl.h>
#include <sys/ioctl.h>
#include <systemd/sd-journal.h>
#include <unistd.h>

#include <Utils.hpp>
#include <boost/asio/io_context.hpp>
#include <sdbusplus/asio/object_server.hpp>

#include <cerrno>
#include <chrono>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <utility>

extern "C"
{
#include <i2c/smbus.h>
#include <linux/i2c-dev.h>
}

static constexpr bool debug = false;

static constexpr unsigned int defaultPollSec = 1;
static constexpr unsigned int sensorFailedPollSec = 5;
static unsigned int intrusionSensorPollSec = defaultPollSec;
static constexpr const char* hwIntrusionValStr =
    "xyz.openbmc_project.Chassis.Intrusion.Status.HardwareIntrusion";
static constexpr const char* normalValStr =
    "xyz.openbmc_project.Chassis.Intrusion.Status.Normal";
static constexpr const char* manualRearmStr =
    "xyz.openbmc_project.Chassis.Intrusion.RearmMode.Manual";
static constexpr const char* autoRearmStr =
    "xyz.openbmc_project.Chassis.Intrusion.RearmMode.Automatic";

// SMLink Status Register
const static constexpr size_t pchStatusRegIntrusion = 0x04;

// Status bit field masks
const static constexpr size_t pchRegMaskIntrusion = 0x01;

// Value to clear intrusion status hwmon file
const static constexpr size_t intrusionStatusHwmonClearValue = 0;

void ChassisIntrusionSensor::updateValue(const size_t& value)
{
    std::string newValue = value != 0 ? hwIntrusionValStr : normalValStr;

    // Take no action if the hardware status does not change
    // Same semantics as Sensor::updateValue(const double&)
    if (newValue == mValue)
    {
        return;
    }

    if constexpr (debug)
    {
        std::cout << "Update value from " << mValue << " to " << newValue
                  << "\n";
    }

    // Automatic Rearm mode allows direct update
    // Manual Rearm mode requires a rearm action to clear the intrusion
    // status
    if (!mAutoRearm)
    {
        if (newValue == normalValStr)
        {
            // Chassis is first closed from being open. If it has been
            // rearmed externally, reset the flag, update mValue and
            // return, without having to write "Normal" to DBus property
            // (because the rearm action already did).
            // Otherwise, return with no more action.
            if (mRearmFlag)
            {
                mRearmFlag = false;
                mValue = newValue;
            }
            return;
        }
    }

    // Flush the rearm flag everytime it allows an update to Dbus
    mRearmFlag = false;

    // indicate that it is internal set call
    mOverridenState = false;
    mInternalSet = true;
    mIface->set_property("Status", newValue);
    mInternalSet = false;

    mValue = newValue;
}

int ChassisIntrusionPchSensor::readSensor()
{
    int32_t statusMask = pchRegMaskIntrusion;
    int32_t statusReg = pchStatusRegIntrusion;

    int32_t value = i2c_smbus_read_byte_data(mBusFd, statusReg);
    if constexpr (debug)
    {
        std::cout << "Pch type: raw value is " << value << "\n";
    }

    if (value < 0)
    {
        std::cerr << "i2c_smbus_read_byte_data failed \n";
        return -1;
    }

    // Get status value with mask
    value &= statusMask;

    if constexpr (debug)
    {
        std::cout << "Pch type: masked raw value is " << value << "\n";
    }
    return value;
}

void ChassisIntrusionPchSensor::pollSensorStatus()
{
    std::weak_ptr<ChassisIntrusionPchSensor> weakRef = weak_from_this();

    // setting a new experation implicitly cancels any pending async wait
    mPollTimer.expires_after(std::chrono::seconds(intrusionSensorPollSec));

    mPollTimer.async_wait([weakRef](const boost::system::error_code& ec) {
        // case of being canceled
        if (ec == boost::asio::error::operation_aborted)
        {
            std::cerr << "Timer of intrusion sensor is cancelled\n";
            return;
        }

        std::shared_ptr<ChassisIntrusionPchSensor> self = weakRef.lock();
        if (!self)
        {
            std::cerr << "ChassisIntrusionSensor no self\n";
            return;
        }

        int value = self->readSensor();
        if (value < 0)
        {
            intrusionSensorPollSec = sensorFailedPollSec;
        }
        else
        {
            intrusionSensorPollSec = defaultPollSec;
            self->updateValue(value);
        }

        // trigger next polling
        self->pollSensorStatus();
    });
}

int ChassisIntrusionGpioSensor::readSensor()
{
    mGpioLine.event_read();
    auto value = mGpioLine.get_value();
    if constexpr (debug)
    {
        std::cout << "Gpio type: raw value is " << value << "\n";
    }
    return value;
}

void ChassisIntrusionGpioSensor::pollSensorStatus()
{
    mGpioFd.async_wait(boost::asio::posix::stream_descriptor::wait_read,
                       [this](const boost::system::error_code& ec) {
        if (ec == boost::system::errc::bad_file_descriptor)
        {
            return; // we're being destroyed
        }

        if (ec)
        {
            std::cerr << "Error on GPIO based intrusion sensor wait event\n";
        }
        else
        {
            int value = readSensor();
            if (value >= 0)
            {
                updateValue(value);
            }
            // trigger next polling
            pollSensorStatus();
        }
    });
}

int ChassisIntrusionHwmonSensor::readSensor()
{
    int value = 0;

    std::fstream stream(mHwmonPath, std::ios::in | std::ios::out);
    if (!stream.good())
    {
        std::cerr << "Error reading status at " << mHwmonPath << "\n";
        return -1;
    }

    std::string line;
    if (!std::getline(stream, line))
    {
        std::cerr << "Error reading status at " << mHwmonPath << "\n";
        return -1;
    }

    try
    {
        value = std::stoi(line);
        if constexpr (debug)
        {
            std::cout << "Hwmon type: raw value is " << value << "\n";
        }
    }
    catch (const std::invalid_argument& e)
    {
        std::cerr << "Error reading status at " << mHwmonPath << " : "
                  << e.what() << "\n";
        return -1;
    }

    // Reset chassis intrusion status after every reading
    stream << intrusionStatusHwmonClearValue;

    return value;
}

void ChassisIntrusionHwmonSensor::pollSensorStatus()
{
    std::weak_ptr<ChassisIntrusionHwmonSensor> weakRef = weak_from_this();

    // setting a new experation implicitly cancels any pending async wait
    mPollTimer.expires_after(std::chrono::seconds(intrusionSensorPollSec));

    mPollTimer.async_wait([weakRef](const boost::system::error_code& ec) {
        // case of being canceled
        if (ec == boost::asio::error::operation_aborted)
        {
            std::cerr << "Timer of intrusion sensor is cancelled\n";
            return;
        }

        std::shared_ptr<ChassisIntrusionHwmonSensor> self = weakRef.lock();
        if (!self)
        {
            std::cerr << "ChassisIntrusionSensor no self\n";
            return;
        }

        int value = self->readSensor();
        if (value < 0)
        {
            intrusionSensorPollSec = sensorFailedPollSec;
        }
        else
        {
            intrusionSensorPollSec = defaultPollSec;
            self->updateValue(value);
        }

        // trigger next polling
        self->pollSensorStatus();
    });
}

int ChassisIntrusionSensor::setSensorValue(const std::string& req,
                                           std::string& propertyValue)
{
    if (!mInternalSet)
    {
        /*
           1. Assuming that setting property in Automatic mode causes
           no effect but only event logs and propertiesChanged signal
           (because the property will be updated continuously to the
           current hardware status anyway), only update Status property
           and raise rearm flag in Manual rearm mode.
           2. Only accept Normal value from an external call.
        */
        if (!mAutoRearm && req == normalValStr)
        {
            mRearmFlag = true;
            propertyValue = req;
            mOverridenState = true;
        }
    }
    else if (!mOverridenState)
    {
        propertyValue = req;
    }
    else
    {
        return 1;
    }
    // Send intrusion event to Redfish
    if (mValue == normalValStr && propertyValue != normalValStr)
    {
        sd_journal_send("MESSAGE=%s", "Chassis intrusion assert event",
                        "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
                        "OpenBMC.0.1.ChassisIntrusionDetected", NULL);
    }
    else if (mValue == hwIntrusionValStr && propertyValue == normalValStr)
    {
        sd_journal_send("MESSAGE=%s", "Chassis intrusion de-assert event",
                        "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
                        "OpenBMC.0.1.ChassisIntrusionReset", NULL);
    }
    return 1;
}

void ChassisIntrusionSensor::start()
{
    mIface->register_property(
        "Status", mValue,
        [&](const std::string& req, std::string& propertyValue) {
        return setSensorValue(req, propertyValue);
    });
    std::string rearmStr = mAutoRearm ? autoRearmStr : manualRearmStr;
    mIface->register_property("Rearm", rearmStr);
    mIface->initialize();
    pollSensorStatus();
}

ChassisIntrusionSensor::ChassisIntrusionSensor(
    bool autoRearm, sdbusplus::asio::object_server& objServer) :
    mValue(normalValStr),
    mAutoRearm(autoRearm), mObjServer(objServer)
{
    mIface = mObjServer.add_interface("/xyz/openbmc_project/Chassis/Intrusion",
                                      "xyz.openbmc_project.Chassis.Intrusion");
}

ChassisIntrusionPchSensor::ChassisIntrusionPchSensor(
    bool autoRearm, boost::asio::io_context& io,
    sdbusplus::asio::object_server& objServer, int busId, int slaveAddr) :
    ChassisIntrusionSensor(autoRearm, objServer),
    mPollTimer(io)
{
    if (busId < 0 || slaveAddr <= 0)
    {
        throw std::invalid_argument("Invalid i2c bus " + std::to_string(busId) +
                                    " address " + std::to_string(slaveAddr) +
                                    "\n");
    }

    mSlaveAddr = slaveAddr;

    std::string devPath = "/dev/i2c-" + std::to_string(busId);
    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
    mBusFd = open(devPath.c_str(), O_RDWR | O_CLOEXEC);
    if (mBusFd < 0)
    {
        throw std::invalid_argument("Unable to open " + devPath + "\n");
    }

    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
    if (ioctl(mBusFd, I2C_SLAVE_FORCE, mSlaveAddr) < 0)
    {
        throw std::runtime_error("Unable to set device address\n");
    }

    unsigned long funcs = 0;

    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
    if (ioctl(mBusFd, I2C_FUNCS, &funcs) < 0)
    {
        throw std::runtime_error("Don't support I2C_FUNCS\n");
    }

    if ((funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA) == 0U)
    {
        throw std::runtime_error(
            "Do not have I2C_FUNC_SMBUS_READ_BYTE_DATA \n");
    }
}

ChassisIntrusionGpioSensor::ChassisIntrusionGpioSensor(
    bool autoRearm, boost::asio::io_context& io,
    sdbusplus::asio::object_server& objServer, bool gpioInverted) :
    ChassisIntrusionSensor(autoRearm, objServer),
    mGpioInverted(gpioInverted), mGpioFd(io)
{
    mGpioLine = gpiod::find_line(mPinName);
    if (!mGpioLine)
    {
        throw std::invalid_argument("Error finding gpio pin name: " + mPinName +
                                    "\n");
    }
    mGpioLine.request(
        {"ChassisIntrusionSensor", gpiod::line_request::EVENT_BOTH_EDGES,
         mGpioInverted ? gpiod::line_request::FLAG_ACTIVE_LOW : 0});

    auto gpioLineFd = mGpioLine.event_get_fd();
    if (gpioLineFd < 0)
    {
        throw std::invalid_argument("Failed to get " + mPinName + " fd\n");
    }

    mGpioFd.assign(gpioLineFd);
}

ChassisIntrusionHwmonSensor::ChassisIntrusionHwmonSensor(
    bool autoRearm, boost::asio::io_context& io,
    sdbusplus::asio::object_server& objServer, std::string hwmonName) :
    ChassisIntrusionSensor(autoRearm, objServer),
    mHwmonName(std::move(hwmonName)), mPollTimer(io)
{
    std::vector<fs::path> paths;

    if (!findFiles(fs::path("/sys/class/hwmon"), mHwmonName, paths))
    {
        throw std::invalid_argument("Failed to find hwmon path in sysfs\n");
    }

    if (paths.empty())
    {
        throw std::invalid_argument("Hwmon file " + mHwmonName +
                                    " can't be found in sysfs\n");
    }

    if (paths.size() > 1)
    {
        std::cerr << "Found more than 1 hwmon file to read chassis intrusion"
                  << " status. Taking the first one. \n";
    }

    // Expecting only one hwmon file for one given chassis
    mHwmonPath = paths[0].string();

    if constexpr (debug)
    {
        std::cout << "Found " << paths.size()
                  << " paths for intrusion status \n"
                  << " The first path is: " << mHwmonPath << "\n";
    }
}

ChassisIntrusionSensor::~ChassisIntrusionSensor()
{
    mObjServer.remove_interface(mIface);
}

ChassisIntrusionPchSensor::~ChassisIntrusionPchSensor()
{
    mPollTimer.cancel();
    if (close(mBusFd) < 0)
    {
        std::cerr << "Failed to close fd " << std::to_string(mBusFd);
    }
}

ChassisIntrusionGpioSensor::~ChassisIntrusionGpioSensor()
{
    mGpioFd.close();
    if (mGpioLine)
    {
        mGpioLine.release();
    }
}

ChassisIntrusionHwmonSensor::~ChassisIntrusionHwmonSensor()
{
    mPollTimer.cancel();
}
