#pragma once

#include "config.h"

#include "occ_events.hpp"

#include <unistd.h>

#include <filesystem>
#include <functional>
namespace open_power
{
namespace occ
{

namespace fs = std::filesystem;

constexpr auto PRESENCE_ERROR_PATH =
    "org.open_power.OCC.Firmware.Error.PresenceMismatch";
constexpr auto SAFE_ERROR_PATH = "org.open_power.OCC.Device.Error.SafeState";
constexpr auto MISSING_OCC_SENSORS_PATH =
    "org.open_power.OCC.Firmware.Error.MissingOCCSensors";

/** @class Error
 *  @brief Monitors for OCC device error condition
 */
class Error
{
  public:
    Error() = delete;
    Error(const Error&) = delete;
    Error& operator=(const Error&) = delete;
    Error(Error&&) = default;
    Error& operator=(Error&&) = default;

    /** @brief Constructs the Error object
     *
     *  @param[in] event    - reference to sd_event unique_ptr
     *  @param[in] file     - File used by driver to communicate errors
     *  @param[in] callBack - Optional function callback on error condition
     */
    Error(EventPtr& event, const fs::path& file,
          std::function<void(int)> callBack = nullptr) :
        event(event), file(file), callBack(callBack)
    {
        // Nothing to do here.
    }

    virtual ~Error()
    {
        if (fd >= 0)
        {
            close(fd);
        }
    }

    /** @class Descriptor
     *  @brief Contains data relevant to an error that occurred.
     */
    class Descriptor
    {
      public:
        Descriptor(const Descriptor&) = default;
        Descriptor& operator=(const Descriptor&) = default;
        Descriptor(Descriptor&&) = default;
        Descriptor& operator=(Descriptor&&) = default;

        Descriptor() : log(false), err(0), callout(nullptr), path(nullptr) {}

        /** @brief Constructs the Descriptor object
         *
         *  @param[in] path - the DBus error path
         *  @param[in] err - Optional error return code
         *  @param[in] callout - Optional PEL callout path
         */
        Descriptor(const char* path, int err = 0,
                   const char* callout = nullptr) :
            log(true), err(err), callout(callout), path(path)
        {}

        bool log;
        int err;
        const char* callout;
        const char* path;
    };

    /** @brief Starts to monitor for error conditions
     *
     *  @param[in] poll - Indicates whether or not the error file should
     *                    actually be polled for changes. Disabling polling is
     *                    necessary for error files that don't support the poll
     *                    file operation.
     */
    void addWatch(bool poll = true);

    /** @brief Removes error watch */
    void removeWatch();

    inline void setFile(const fs::path& f)
    {
        file = f;
    }

  private:
    /** @brief sd_event wrapped in unique_ptr */
    EventPtr& event;

    /** @brief event source wrapped in unique_ptr */
    EventSourcePtr eventSource;

    /** @brief Current state of error watching */
    bool watching = false;

    /** @brief attaches FD to events and sets up callback handler */
    void registerCallBack();

    /** @brief Opens the file and populates fd */
    void openFile();

    /** @brief Callback handler when the FD has some activity on it
     *
     *  @param[in] es       - Populated event source
     *  @param[in] fd       - Associated File descriptor
     *  @param[in] revents  - Type of event
     *  @param[in] userData - User data that was passed during registration
     *
     *  @return             - 0 or positive number on success and negative
     *                        errno otherwise
     */
    static int processEvents(sd_event_source* es, int fd, uint32_t revents,
                             void* userData);

    /** @brief When the error event is received, analyzes it
     *         and makes a callback to error handler if the
     *         content denotes an error condition
     */
    virtual void analyzeEvent();

  protected:
    /** @brief File descriptor to watch for errors */
    int fd = -1;

    /** Error file */
    fs::path file;

    /** @brief Optional function to call on error scenario */
    std::function<void(int)> callBack;

    /** @brief Reads file data
     *
     *  @return data read. Since its a /sysfs entry,
     *          it would be a string
     */
    std::string readFile(int) const;
};

} // namespace occ
} // namespace open_power
