#include <stm32f302xc.h>
#include <stm32f3xx_hal.h>
#include <stm32f3xx_hal_conf.h>
#include <vn-interface/helper.h>
#include <vn-interface/frames.h>
#include <can-transceiver-lib/can1.h>
#include <can-transceiver-lib/endec.hpp>
#include "canhalal.h"

template <typename payload_t>
HAL_StatusTypeDef spi_read(SPI_HandleTypeDef *hspi, vn::pkg_request_read_t *pRequestMOSI, vn::pkg_response_t<payload_t> *pResponseMISO) {
    HAL_StatusTypeDef status = HAL_OK;
    vn::header_t::response_t requestMISO;

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);
    status = HAL_SPI_TransmitReceive(hspi, (uint8_t *)(pRequestMOSI),
                                     (uint8_t *)(&requestMISO),  // not relevant, but there to function
                                     sizeof(*pRequestMOSI), 100);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET);

    HAL_Delay(1);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);

    vn::pkg_response_t<payload_t> responseMOSI;

    status = HAL_SPI_TransmitReceive(hspi,
                                     (uint8_t *)(&responseMOSI),  // just empty byte to allow the slave to transmit
                                     (uint8_t *)(pResponseMISO), sizeof(*pResponseMISO), 100);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET);
    return status;
}

template <typename payload_t>
HAL_StatusTypeDef spi_write(SPI_HandleTypeDef *hspi, vn::pkg_request_write_t<payload_t> *pRequestMOSI, vn::pkg_response_t<payload_t> *pResponseMISO) {
    HAL_StatusTypeDef status = HAL_OK;
    vn::header_t::response_t requestMISO;

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);
    status = HAL_SPI_TransmitReceive(hspi, (uint8_t *)(pRequestMOSI),
                                     (uint8_t *)(&requestMISO),  // not relevant, but there to function
                                     sizeof(*pRequestMOSI), 100);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET);

    HAL_Delay(1);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);

    vn::pkg_response_t<payload_t> responseMOSI;

    status = HAL_SPI_TransmitReceive(hspi,
                                     (uint8_t *)(&responseMOSI),  // just empty byte to allow the slave to transmit
                                     (uint8_t *)(pResponseMISO), sizeof(*pResponseMISO), 100);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET);
    return status;
}

HAL_StatusTypeDef spi2can(SPI_HandleTypeDef *hspi, CAN_HandleTypeDef *hcan);