#pragma once

#ifdef USE_ESP32

#include "esphome/components/canbus/canbus.h"
#include "esphome/core/component.h"

#include <driver/twai.h>

namespace esphome::esp32_can {

enum CanMode : uint8_t {
  CAN_MODE_NORMAL = 0,
  CAN_MODE_LISTEN_ONLY = 1,
};

class ESP32Can final : public canbus::Canbus {
 public:
  void set_rx(int rx) { rx_ = rx; }
  void set_tx(int tx) { tx_ = tx; }
  void set_mode(CanMode mode) { mode_ = mode; }
  void set_tx_queue_len(uint32_t tx_queue_len) { this->tx_queue_len_ = tx_queue_len; }
  void set_rx_queue_len(uint32_t rx_queue_len) { this->rx_queue_len_ = rx_queue_len; }
  void set_tx_enqueue_timeout_ms(uint32_t tx_enqueue_timeout_ms) {
    this->tx_enqueue_timeout_ticks_ = pdMS_TO_TICKS(tx_enqueue_timeout_ms);
  }
  ESP32Can(){};

 protected:
  bool setup_internal() override;
  canbus::Error send_message(struct canbus::CanFrame *frame) override;
  canbus::Error read_message(struct canbus::CanFrame *frame) override;

  int rx_{-1};
  int tx_{-1};
  CanMode mode_{CAN_MODE_NORMAL};
  TickType_t tx_enqueue_timeout_ticks_{};
  optional<uint32_t> tx_queue_len_{};
  optional<uint32_t> rx_queue_len_{};
  twai_handle_t twai_handle_{nullptr};
};

}  // namespace esphome::esp32_can

#endif
