#pragma once

#include <unistd.h>
#include <functional>
#include <experimental/filesystem>
#include "occ_events.hpp"
#include "config.h"
namespace open_power
{
namespace occ
{

namespace fs = std::experimental::filesystem;

/** @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()> callBack = nullptr) :
            event(event),
            file(fs::path(DEV_PATH) / file),
            callBack(callBack)
        {
            // Nothing to do here.
        }

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

        /** @brief Starts to monitor for error conditions */
        void addWatch();

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

    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 */
        const fs::path file;

        /** @brief Optional function to call on error scenario */
        std::function<void()> 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
