/**
 * @file gpio.hpp
 * @brief GPIO wrapper component header - Wrapper for ESP-IDF GPIO functionality
 * @author Mahmoud Elmohtady
 * @company Nabd solutions - ASF
 * @copyright Copyright (c) 2025
 */

#ifndef GPIO_HPP
#define GPIO_HPP

#include <cstdint>
#include "driver/gpio.h"
#include "esp_err.h"

/**
 * @brief GPIO pin mode enumeration
 */
enum class GpioMode
{
    INPUT,
    OUTPUT,
    INPUT_PULLUP,
    INPUT_PULLDOWN,
    OUTPUT_OD
};

/**
 * @brief GPIO interrupt type enumeration
 */
enum class GpioIntType
{
    DISABLE,
    RISING_EDGE,
    FALLING_EDGE,
    ANY_EDGE,
    LOW_LEVEL,
    HIGH_LEVEL
};

/**
 * @brief GPIO callback function type
 */
using GpioCallback = void (*)(uint32_t pin, void* arg);

/**
 * @brief GPIO wrapper class
 * 
 * Provides a C++ wrapper for ESP-IDF GPIO functionality.
 * This class encapsulates ESP-IDF GPIO driver functions in an object-oriented interface.
 */
class Gpio
{
public:
    /**
     * @brief Constructor
     * @details Initializes the GPIO wrapper instance
     */
    Gpio();

    /**
     * @brief Destructor
     * @details Cleans up resources and uninstalls ISR if installed
     */
    ~Gpio();

    /**
     * @brief Configure a GPIO pin
     * @param pin GPIO pin number (0-39 for ESP32)
     * @param mode GPIO mode configuration
     * @return true if configured successfully, false otherwise
     * @note This function configures the pin direction, pull-up/down resistors
     */
    bool configure(uint32_t pin, GpioMode mode);

    /**
     * @brief Set GPIO pin level
     * @param pin GPIO pin number
     * @param level Pin level (0 for low, 1 for high)
     * @return true if set successfully, false otherwise
     * @note Only works for output pins
     */
    bool setLevel(uint32_t pin, uint32_t level);

    /**
     * @brief Get GPIO pin level
     * @param pin GPIO pin number
     * @return Pin level (0 for low, 1 for high), or -1 on error
     * @note Works for both input and output pins
     */
    int32_t getLevel(uint32_t pin);

    /**
     * @brief Toggle GPIO pin level
     * @param pin GPIO pin number
     * @return true if toggled successfully, false otherwise
     * @note Only works for output pins
     */
    bool toggleLevel(uint32_t pin);

    /**
     * @brief Install GPIO interrupt service
     * @param flags Allocation flags for interrupt service
     * @return true if installed successfully, false otherwise
     * @note Must be called before attaching interrupts
     */
    bool installIsr(int flags = 0);

    /**
     * @brief Uninstall GPIO interrupt service
     * @return true if uninstalled successfully, false otherwise
     */
    bool uninstallIsr();

    /**
     * @brief Attach interrupt to a GPIO pin
     * @param pin GPIO pin number
     * @param intType Interrupt type
     * @param callback Callback function
     * @param arg Argument passed to callback
     * @return true if attached successfully, false otherwise
     * @note ISR must be installed before calling this function
     */
    bool attachInterrupt(uint32_t pin, GpioIntType intType, GpioCallback callback, void* arg);

    /**
     * @brief Detach interrupt from a GPIO pin
     * @param pin GPIO pin number
     * @return true if detached successfully, false otherwise
     */
    bool detachInterrupt(uint32_t pin);

    /**
     * @brief Enable interrupt for a GPIO pin
     * @param pin GPIO pin number
     * @return true if enabled successfully, false otherwise
     */
    bool enableInterrupt(uint32_t pin);

    /**
     * @brief Disable interrupt for a GPIO pin
     * @param pin GPIO pin number
     * @return true if disabled successfully, false otherwise
     */
    bool disableInterrupt(uint32_t pin);

    /**
     * @brief Check if GPIO pin is valid
     * @param pin GPIO pin number
     * @return true if pin is valid, false otherwise
     */
    static bool isValidPin(uint32_t pin);

private:
    bool m_isrInstalled_;  ///< Flag indicating if ISR is installed
    
    /**
     * @brief Convert GpioMode to ESP-IDF gpio_mode_t
     * @param mode GPIO mode
     * @return ESP-IDF gpio_mode_t
     */
    gpio_mode_t convertMode(GpioMode mode);
    
    /**
     * @brief Convert GpioIntType to ESP-IDF gpio_int_type_t
     * @param intType Interrupt type
     * @return ESP-IDF gpio_int_type_t
     */
    gpio_int_type_t convertIntType(GpioIntType intType);
};

#endif // GPIO_HPP

