#pragma once
#include <cstdint>
#include <strings.h>

/**
 * @brief Handler function pointer type
 * 
 */
typedef void (*intHandlerFunction_t)(void *); 

/**
 * @brief Hardware handle for MCP2521
 * @interface
 * This is an abstraction over the sepific hardware setup, eg. SPI@ESP32 or RP2040
 * 
 */
class I_MCP2521_HardwareHandle {
public:
    /**
     * @brief Registeres a function that is called when the MCP2521 triggers an interrupt
     * 
     * @param handler This function is called when the MCP2521 triggers an interrupt
     * @param arg Arguments passed to the handler-function
     */
    virtual void registerIntHandler(intHandlerFunction_t handler, void * arg) = 0;

    /**
     * @overload
     * @brief justed sends a 8bit command to the MCP2521
     * 
     * @param cmd command to send
     */
    virtual void execute(uint8_t cmd) = 0;

    /**
     * @overload
     * @brief executes a command (8 bit) with an address (8 bit)
     * 
     * @param cmd 8 bit command
     * @param address 8 bit address
     */
    virtual void execute(uint8_t cmd, uint8_t address) = 0;

    /**
     * 
     * @brief Executes a read from the MCP2521 with command, data buffer, length and address
     * @overload
     * 
     * @param cmd Command to MCP2521
     * @param data Data buffer to store the read data
     * @param length How many bytes to read
     * @param address Address to read from
     */
    virtual void read(uint8_t cmd, uint8_t *data, size_t length, uint8_t address) = 0;

    /**
     * @brief Executes a read from the MCP2521 with command, data buffer and length
     * @overload
     * 
     * @param cmd Command to MCP2521
     * @param data Data buffer to store the read data
     * @param length How many bytes to read
     */
    virtual void read(uint8_t cmd, uint8_t *data, size_t length) = 0;
    
    /**
     * @brief Executes a read from the MCP2521 with command and address, returns just one byte
     * 
     * @param cmd Command to MCP2521
     * @param address Address to read from
     * @return uint8_t 
     */
    virtual uint8_t read(uint8_t cmd, uint8_t address) = 0;
    
    /**
     * @brief Executes a read from the MCP2521 with command, returns just one byte
     * 
     * @param cmd Command to MCP2521
     * @return uint8_t 
     */
    virtual uint8_t read(uint8_t cmd) = 0;
    
    /**
     * @brief Writes data to the MCP2521 with command, data buffer, length and address
     * 
     * @param cmd Command to MCP2521
     * @param data Data buffer to write
     * @param length Length of the data buffer
     * @param address Where to write the data
     */
    virtual void write(uint8_t cmd, uint8_t *data, size_t length, uint8_t address) = 0;
    
    /**
     * @brief Wirites data to the MCP2521 with command, data buffer and length
     * 
     * @param cmd Command to MCP2521
     * @param data Data buffer to write
     * @param length Length of the data buffer
     */
    virtual void write(uint8_t cmd, uint8_t *data, size_t length) = 0;
    
    /**
     * @brief Writes data to the MCP2521 with command, data (on byte) and address
     * 
     * @param cmd Command to MCP2521
     * @param data Data byte to write
     * @param address Where to write the data
     */
    virtual void write(uint8_t cmd, uint8_t data, uint8_t address) = 0;
    
    /**
     * @brief Writes to the MCP2521 with command and data (one byte)
     * 
     * @param cmd Command to MCP2521
     * @param data Data byte to write
     */
    virtual void write(uint8_t cmd, uint8_t data) = 0;
};

