#include "speaker.h"

i2s_chan_handle_t tx_chan;

static const char *TAG = "speaker_driver";

esp_err_t play_raw_stop_queue(const char *fp, QueueHandle_t stop_handle) {
  FILE *fh = fopen(fp, "rb");
  if (fh == NULL)
  {
    ESP_LOGE(TAG, "Failed to open file");
    return ESP_ERR_INVALID_ARG;
  }

  // create a writer buffer
  uint8_t *read_buf = (uint8_t*) calloc(AUDIO_BUFFER, sizeof(uint8_t));
  uint16_t *write_buf = (uint16_t*) calloc(AUDIO_BUFFER, sizeof(uint16_t));
  size_t bytes_read = 0;
  size_t bytes_written = 0;

  esp_err_t channel_enable_result = i2s_channel_enable(tx_chan);
  ESP_ERROR_CHECK_WITHOUT_ABORT(channel_enable_result);
  if (channel_enable_result != ESP_OK) {
    return channel_enable_result;
  }

  bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
  for (int i = 0; i < bytes_read; i++) {
      write_buf[i] = read_buf[i] << 4;
  }

//   i2s_channel_enable(tx_handle);

  while (bytes_read > 0) {
    // write the buffer to the i2s
    // ESP_LOGI(TAG, "Writing: ");
    // for (int i = 0; i < words_read; i++) {
    //   int16_t val = buf[i];
    //   printf("%s0x%04X ", (val < 0 ? "-" : "+"), (val < 0 ? -val : val));
    // }>
    i2s_channel_write(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY);
    bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
    for (int i = 0; i < bytes_read; i++) {
      write_buf[i] = read_buf[i] << 4;
    }
    uint8_t recv  = 0;
    if (xQueueReceive(stop_handle, &recv, 0)) {
      break;
    }
    vTaskDelay(pdMS_TO_TICKS(10));
  }

  i2s_channel_disable(tx_chan);
  free(read_buf);
  free(write_buf);
  fclose(fh);

  return ESP_OK;
}

esp_err_t play_raw(const char *fp) {
  FILE *fh = fopen(fp, "rb");
  if (fh == NULL)
  {
    ESP_LOGE(TAG, "Failed to open file");
    return ESP_ERR_INVALID_ARG;
  }

  // create a writer buffer
  uint8_t *read_buf = (uint8_t*) calloc(AUDIO_BUFFER, sizeof(uint8_t));
  uint16_t *write_buf = (uint16_t*) calloc(AUDIO_BUFFER, sizeof(uint16_t));
  size_t bytes_read = 0;
  size_t bytes_written = 0;

  esp_err_t channel_enable_result = i2s_channel_enable(tx_chan);
  ESP_ERROR_CHECK_WITHOUT_ABORT(channel_enable_result);
  if (channel_enable_result != ESP_OK) {
    return channel_enable_result;
  }

  bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
  for (int i = 0; i < bytes_read; i++) {
      write_buf[i] = read_buf[i] << 4;
  }

//   i2s_channel_enable(tx_handle);

  while (bytes_read > 0) {
    // write the buffer to the i2s
    // ESP_LOGI(TAG, "Writing: ");
    // for (int i = 0; i < words_read; i++) {
    //   int16_t val = buf[i];
    //   printf("%s0x%04X ", (val < 0 ? "-" : "+"), (val < 0 ? -val : val));
    // }>
    i2s_channel_write(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY);
    bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
    for (int i = 0; i < bytes_read; i++) {
      write_buf[i] = read_buf[i] << 4;
    }
    vTaskDelay(pdMS_TO_TICKS(10));
  }

  i2s_channel_disable(tx_chan);
  free(read_buf);
  free(write_buf);
  fclose(fh);

  return ESP_OK;
}

void init_speaker(void) {
    i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
    ESP_ERROR_CHECK(i2s_new_channel(&tx_chan_cfg, &tx_chan, NULL));

    i2s_std_config_t tx_std_cfg = {
        .clk_cfg  = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
        .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO),
        .gpio_cfg = {
            .mclk = I2S_GPIO_UNUSED,
            .bclk = SPEAKER_PIN_BCLK,
            .ws   = SPEAKER_PIN_WS,
            .dout = SPEAKER_PIN_DOUT,
            .din  = GPIO_NUM_NC,
            .invert_flags = {
                .mclk_inv = false,
                .bclk_inv = false,
                .ws_inv   = false,
            },
        },
    };
    ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &tx_std_cfg));
}

void play_example() {
  ESP_ERROR_CHECK_WITHOUT_ABORT(play_raw("/sdcard/o.pcm"));
}
