#ifndef LINUX_BOARDTEST_SPITESTCLASS_H_
#define LINUX_BOARDTEST_SPITESTCLASS_H_

#include <fsfw_hal/common/gpio/GpioIF.h>
#include <fsfw_hal/linux/spi/SpiCookie.h>
#include <test/testtasks/TestTask.h>

#include <vector>

class SpiTestClass: public TestTask {
public:
    enum TestModes {
        NONE,
        MGM_LIS3MDL,
        MGM_RM3100,
        GYRO_L3GD20H,
    };

    TestModes testMode;

    SpiTestClass(object_id_t objectId, GpioIF* gpioIF);

    ReturnValue_t performOneShotAction() override;
    ReturnValue_t performPeriodicAction() override;
private:

    GpioIF* gpioIF;

    std::array<uint8_t, 128> recvBuffer;
    std::array<uint8_t, 128> sendBuffer;
    struct spi_ioc_transfer spiTransferStruct = {};

    void performRm3100Test(uint8_t mgmId);
    void performLis3MdlTest(uint8_t lis3Id);
    void performL3gTest(uint8_t l3gId);

    /* ACS board specific code which pulls all GPIOs high */
    void acsInit();

    /* ACS board specific variables */
#ifdef RASPBERRY_PI
    uint8_t mgm0Lis3mdlChipSelect = 0;
    uint8_t mgm1Rm3100ChipSelect = 1;
    uint8_t gyro0AdisChipSelect = 5;
    uint8_t gyro1L3gd20ChipSelect = 6;
    uint8_t gyro2L3gd20ChipSelect = 4;
    uint8_t mgm2Lis3mdlChipSelect = 17;
    uint8_t mgm3Rm3100ChipSelect = 27;
#elif defined(XIPHOS_Q7S)
    uint8_t mgm0Lis3mdlChipSelect = 5;
    uint8_t mgm1Rm3100ChipSelect = 17;
    uint8_t gyro0AdisResetLine = 20;
    uint8_t gyro0AdisChipSelect = 21;
    uint8_t gyro1L3gd20ChipSelect = 10;
    uint8_t gyro2L3gd20ChipSelect = 3;
    uint8_t mgm2Lis3mdlChipSelect = 0;
    uint8_t mgm3Rm3100ChipSelect = 23;
#else
    uint8_t mgm0Lis3mdlChipSelect = 0;
    uint8_t mgm1Rm3100ChipSelect = 0;
    uint8_t gyro0AdisResetLine = 0;
    uint8_t gyro0AdisChipSelect = 0;
    uint8_t gyro1L3gd20ChipSelect = 0;
    uint8_t gyro2L3gd20ChipSelect = 0;
    uint8_t mgm2Lis3mdlChipSelect = 0;
    uint8_t mgm3Rm3100ChipSelect = 0;
#endif

    static constexpr uint8_t STM_READ_MASK = 0b1000'0000;
    static constexpr uint8_t RM3100_READ_MASK = STM_READ_MASK;
    static constexpr uint8_t STM_AUTO_INCR_MASK = 0b0100'0000;

    void setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed);

    void writeStmRegister(int fd, gpioId_t chipSelect, uint8_t reg, uint8_t value,
            bool autoIncrement);
    void writeMultipleStmRegisters(int fd, gpioId_t chipSelect, uint8_t reg, uint8_t* values,
            size_t len);
    void writeMultipleRegisters(int fd, gpioId_t chipSelect, uint8_t reg, uint8_t *values,
            size_t len);
    void writeRegister(int fd, gpioId_t chipSelect, uint8_t reg, uint8_t value);

    uint8_t readRm3100Register(int fd, gpioId_t chipSelect, uint8_t reg);
    uint8_t readStmRegister(int fd, gpioId_t chipSelect, uint8_t reg, bool autoIncrement);
    uint8_t readRegister(int fd, gpioId_t chipSelect, uint8_t reg);
    void readMultipleStmRegisters(int fd, gpioId_t chipSelect, uint8_t reg, uint8_t *reply,
            size_t len);
    void readMultipleRegisters(int fd, gpioId_t chipSelect, uint8_t reg,
            uint8_t* reply, size_t len);

};




#endif /* LINUX_BOARDTEST_SPITESTCLASS_H_ */