#include "extensions/openpower-pels/data_interface.hpp"
#include "extensions/openpower-pels/host_interface.hpp"

#include <fcntl.h>

#include <filesystem>
#include <sdeventplus/source/io.hpp>

#include <gmock/gmock.h>

namespace openpower
{
namespace pels
{

class MockDataInterface : public DataInterfaceBase
{
  public:
    MockDataInterface()
    {
    }
    MOCK_METHOD(std::string, getMachineTypeModel, (), (const override));
    MOCK_METHOD(std::string, getMachineSerialNumber, (), (const override));
    MOCK_METHOD(std::string, getServerFWVersion, (), (const override));
    MOCK_METHOD(std::string, getBMCFWVersion, (), (const override));

    void changeHostState(bool newState)
    {
        setHostState(newState);
    }

    void setHMCManaged(bool managed)
    {
        _hmcManaged = managed;
    }
};

/**
 * @brief The mock HostInterface class
 *
 * This replaces the PLDM calls with a FIFO for the asynchronous
 * responses.
 */
class MockHostInterface : public HostInterface
{
  public:
    /**
     * @brief Constructor
     *
     * @param[in] event - The sd_event object
     * @param[in] dataIface - The DataInterface class
     */
    MockHostInterface(sd_event* event, DataInterfaceBase& dataIface) :
        HostInterface(event, dataIface)
    {
        char templ[] = "/tmp/cmdfifoXXXXXX";
        std::filesystem::path dir = mkdtemp(templ);
        _fifo = dir / "fifo";
    }

    /**
     * @brief Destructor
     */
    virtual ~MockHostInterface()
    {
        std::filesystem::remove_all(_fifo.parent_path());
    }

    MOCK_METHOD(CmdStatus, sendNewLogCmd, (uint32_t, uint32_t), (override));

    /**
     * @brief Cancels waiting for a command response
     */
    virtual void cancelCmd() override
    {
        _inProgress = false;
        _source = nullptr;
    }

    /**
     * @brief Returns the amount of time to wait before retrying after
     *        a failed send command.
     *
     * @return milliseconds - The amount of time to wait
     */
    virtual std::chrono::milliseconds getSendRetryDelay() const override
    {
        return std::chrono::milliseconds(2);
    }

    /**
     * @brief Returns the amount of time to wait before retrying after
     *        a command receive.
     *
     * @return milliseconds - The amount of time to wait
     */
    virtual std::chrono::milliseconds getReceiveRetryDelay() const override
    {
        return std::chrono::milliseconds(2);
    }

    /**
     * @brief Returns the amount of time to wait before retrying if the
     *        host firmware's PEL storage was full and it can't store
     *        any more logs until it is freed up somehow.
     *
     * @return milliseconds - The amount of time to wait
     */
    virtual std::chrono::milliseconds getHostFullRetryDelay() const override
    {
        return std::chrono::milliseconds(20);
    }

    /**
     * @brief Returns the number of commands processed
     */
    size_t numCmdsProcessed() const
    {
        return _cmdsProcessed;
    }

    /**
     * @brief Writes the data passed in to the FIFO
     *
     * @param[in] hostResponse - use a 0 to indicate success
     *
     * @return CmdStatus - success or failure
     */
    CmdStatus send(uint8_t hostResponse)
    {
        // Create a FIFO once.
        if (!std::filesystem::exists(_fifo))
        {
            if (mkfifo(_fifo.c_str(), 0622))
            {
                ADD_FAILURE() << "Failed mkfifo " << _fifo << strerror(errno);
                exit(-1);
            }
        }

        // Open it and register the reponse callback to
        // be used on FD activity.
        int fd = open(_fifo.c_str(), O_NONBLOCK | O_RDWR);
        EXPECT_TRUE(fd >= 0) << "Unable to open FIFO";

        auto callback = [this](sdeventplus::source::IO& source, int fd,
                               uint32_t events) {
            this->receive(source, fd, events);
        };

        try
        {
            _source = std::make_unique<sdeventplus::source::IO>(
                _event, fd, EPOLLIN,
                std::bind(callback, std::placeholders::_1,
                          std::placeholders::_2, std::placeholders::_3));
        }
        catch (std::exception& e)
        {
            ADD_FAILURE() << "Event exception: " << e.what();
            close(fd);
            return CmdStatus::failure;
        }

        // Write the fake host reponse to the FIFO
        auto bytesWritten = write(fd, &hostResponse, sizeof(hostResponse));
        EXPECT_EQ(bytesWritten, sizeof(hostResponse));

        _inProgress = true;

        return CmdStatus::success;
    }

  protected:
    /**
     * @brief Reads the data written to the fifo and then calls
     *        the subscriber's callback.
     *
     * Nonzero data indicates a command failure (for testing bad path).
     *
     * @param[in] source - The event source object
     * @param[in] fd - The file descriptor used
     * @param[in] events - The event bits
     */
    void receive(sdeventplus::source::IO& source, int fd,
                 uint32_t events) override
    {
        if (!(events & EPOLLIN))
        {
            return;
        }

        _inProgress = false;

        int newFD = open(_fifo.c_str(), O_NONBLOCK | O_RDONLY);
        ASSERT_TRUE(newFD >= 0) << "Failed to open FIFO";

        // Read the host success/failure response from the FIFO.
        uint8_t data;
        auto bytesRead = read(newFD, &data, sizeof(data));
        EXPECT_EQ(bytesRead, sizeof(data));

        close(newFD);

        ResponseStatus status = ResponseStatus::success;
        if (data != 0)
        {
            status = ResponseStatus::failure;
        }

        if (_responseFunc)
        {
            (*_responseFunc)(status);
        }

        // Keep account of the number of commands responses for testing.
        _cmdsProcessed++;
    }

  private:
    /**
     * @brief The event source for the fifo
     */
    std::unique_ptr<sdeventplus::source::IO> _source;

    /**
     * @brief the path to the fifo
     */
    std::filesystem::path _fifo;

    /**
     * @brief The number of commands processed
     */
    size_t _cmdsProcessed = 0;
};

} // namespace pels
} // namespace openpower
