#include "Config.h"
#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>
#include <math.h>
#include <pulse/error.h>
#include <pulse/simple.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

SDL_AtomicInt is_speaking;
SDL_AtomicInt app_running;
float shared_rms = 0.0f;

int SDLCALL audio_thread_func(void *data) {
  (void)data;
  pa_sample_spec ss = {
      .format = PA_SAMPLE_S16LE, .rate = SAMPLE_RATE, .channels = 1};
  pa_buffer_attr attr = {.maxlength = -1,
                         .tlength = -1,
                         .prebuf = -1,
                         .minreq = -1,
                         .fragsize = BUFFER_SIZE * 2};
  int error;
  pa_simple *s = pa_simple_new(NULL, "PNDacc", PA_STREAM_RECORD, NULL, "Record",
                               &ss, NULL, &attr, &error);
  if (!s)
    return -1;
  int16_t buffer[BUFFER_SIZE];
  while (SDL_GetAtomicInt(&app_running)) {
    if (pa_simple_read(s, buffer, sizeof(buffer), &error) < 0)
      break;
    double sum_squares = 0;
    for (int i = 0; i < BUFFER_SIZE; i++)
      sum_squares += (double)buffer[i] * buffer[i];
    float rms = (float)sqrt(sum_squares / BUFFER_SIZE);
    shared_rms = rms;
    SDL_SetAtomicInt(&is_speaking, rms > VOLUME_THRESHOLD ? 1 : 0);
  }
  pa_simple_free(s);
  return 0;
}

int main(void) {
  SDL_SetAtomicInt(&app_running, 1);
  if (!SDL_Init(SDL_INIT_VIDEO))
    return 1;
  SDL_Window *window;
  SDL_Renderer *renderer;
  if (!SDL_CreateWindowAndRenderer("PNDacc", 600, 600, 0, &window, &renderer))
    return 1;
  SDL_Texture *tex = IMG_LoadTexture(renderer, "profile.png");
  if (!tex)
    fprintf(stderr, "[ERROR] 'profile.png' not found!\n");
  SDL_Thread *audio_thread =
      SDL_CreateThread(audio_thread_func, "AudioThread", NULL);
  float visual_rms = 0.0f;
  while (SDL_GetAtomicInt(&app_running)) {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
      if (event.type == SDL_EVENT_QUIT)
        SDL_SetAtomicInt(&app_running, 0);
    }
    float target_rms = shared_rms;
    if (target_rms < VOLUME_THRESHOLD)
      target_rms = 0.0f;
    visual_rms += (target_rms - visual_rms) * LERP_SPEED;
    SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
    SDL_RenderClear(renderer);
    float volume_norm = visual_rms / MAX_VOLUME_REF;
    if (volume_norm > 1.0f)
      volume_norm = 1.0f;
    float stretch_y = 1.0f + (volume_norm * SQUASH_STRETCH_INTENSITY);
    float squash_x = 1.0f - (volume_norm * SQUASH_STRETCH_INTENSITY * 0.6f);
    uint64_t ticks = SDL_GetTicks();
    float bob = sinf(ticks * IDLE_BOB_SPEED) * IDLE_BOB_AMP;
    float tilt = sinf(ticks * (IDLE_BOB_SPEED * 0.7f)) * IDLE_TILT_AMP;
    if (tex) {
      float img_w, img_h;
      SDL_GetTextureSize(tex, &img_w, &img_h);
      float scale = 450.0f / (img_h > img_w ? img_h : img_w);
      float base_w = img_w * scale;
      float base_h = img_h * scale;
      float final_w = base_w * squash_x;
      float final_h = base_h * stretch_y;
      SDL_FRect dst = {300.0f - (final_w / 2.0f), 550.0f - final_h + bob,
                       final_w, final_h};
      SDL_FPoint origin = {final_w / 2.0f, final_h};
      SDL_RenderTextureRotated(renderer, tex, NULL, &dst, (double)tilt, &origin,
                               SDL_FLIP_NONE);
    }
    SDL_RenderPresent(renderer);
    SDL_Delay(8);
  }
  SDL_SetAtomicInt(&app_running, 0);
  SDL_WaitThread(audio_thread, NULL);
  if (tex)
    SDL_DestroyTexture(tex);
  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(window);
  SDL_Quit();
  return 0;
}
