#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <cmath>
#include <unistd.h>
#include <iostream>
#include <sys/time.h>
#include <chrono>
#include "scope.h"

// Main window size (location is 0, 0)
int x_window_size = 0;
int y_window_size = 0;
char input_our_audio_device_name[100];

main_window_class *my_main_window = NULL;
audio_window_class *my_audio_window = NULL;
spectrum_window_class *my_spectrum_window = NULL;
piano_window_class *my_piano_window = NULL;
main_buffer_manager_class *my_main_buffer_manager = NULL;
audio_buffer_manager_class *my_audio_buffer_manager = NULL;
spectrum_buffer_manager_class *my_spectrum_buffer_manager = NULL;
piano_process_class *my_piano_process = NULL;

struct piano_data_struct *piano_data_pointer=NULL;

Uint64 last_time;
Uint64 this_time;

// SDL Event to stop application on pressing a key on the keyboard
SDL_Event my_event;
int get_me_out = 0;

int main(int argc, char *argv[])
{

  // function result
  int main_function_result = 0;

  // Get parameters for size
  if (argc < 3)
    {
    printf ("needs x and y size \n");
    exit (0);
    }

  x_window_size = atoi(argv[1]);
  y_window_size = atoi(argv[2]);

  int our_audio_trace_width;
  int our_audio_trace_height;
  int our_spectrum_trace_width;
  int our_spectrum_trace_height;

  Sint16 *my_main_buffer;
  int *return_audio_buffer;
  int *return_spectrum_buffer;

  printf ("window is %d by %d\n", x_window_size, y_window_size);

  // returns zero on success else non-zero
  if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
      printf("error initializing SDL: %s\n", SDL_GetError());
  }

  // returns zero on success else non-zero

  if (TTF_Init() != 0 ){
      printf("error initializing TTF: %s\n", SDL_GetError());
  }

  // Windows
  my_main_window = new main_window_class(x_window_size, y_window_size);
  my_audio_window = new audio_window_class(x_window_size, y_window_size);
  my_spectrum_window = new spectrum_window_class(x_window_size, y_window_size);
  my_piano_window = new piano_window_class(x_window_size, y_window_size);

  // main buffer
  my_main_buffer_manager = new main_buffer_manager_class();

  // audio_buffer
  my_audio_buffer_manager = new audio_buffer_manager_class();

  // spectrum buffer
  my_spectrum_buffer_manager = new spectrum_buffer_manager_class();

  // piano_process
  my_piano_process = new piano_process_class();

  // audio window width and height
  our_audio_trace_width = my_audio_window->get_max_audio_trace_width();
  our_audio_trace_height = my_audio_window->get_max_audio_trace_height();

  // spectrum window width and height
  our_spectrum_trace_width = my_spectrum_window->get_max_spectrum_trace_width();
  our_spectrum_trace_height = my_spectrum_window->get_max_spectrum_trace_height();

  // buffer initializations
  my_main_buffer = my_main_buffer_manager->initial_preparation();
  if (my_main_buffer == NULL)
    {
    printf("error initialize main_buffer\n");
    exit (0);
    }

  main_function_result = my_audio_buffer_manager->initialize_audio
   (our_audio_trace_width, our_audio_trace_height, my_main_buffer);
  if (main_function_result)
    {
    printf("error initialize audio_buffer\n");
    exit (0);
    }

  main_function_result = my_spectrum_buffer_manager->initialize_spectrum
   (our_spectrum_trace_width, our_spectrum_trace_height, my_main_buffer);
  if (main_function_result)
    {
    printf("error initialize spectrum_buffer\n");
    exit (0);
    }

  //Initialize Piano Data Processor
  main_function_result = my_piano_process->initialize_piano_data();
  if (main_function_result)
    {
    printf("error initialize piano processing\n");
    exit (0);
    }

  //Read and process and display loop

  last_time = 0;

  while (get_me_out == 0) {

    while(SDL_PollEvent(&my_event)) {
      printf("got event event type is %d\n", my_event.type);
      switch (my_event.type) {
         case SDL_QUIT: get_me_out = 1;
         case SDL_KEYDOWN: get_me_out = 1;
         break;
      }
    }
    // SDL_Delay(100);

    my_main_buffer = my_main_buffer_manager->read_main_buffer();
    if (my_main_buffer == NULL)
      {
      printf("error resding into main_buffer\n");
      exit (0);
      }

    return_audio_buffer = my_audio_buffer_manager->process_audio();
    if (return_audio_buffer == NULL)
      {
      printf("error processing audio to return_audio_buffer\n");
      exit (0);
      }

    return_spectrum_buffer = my_spectrum_buffer_manager->process_spectrum();

    //gettimeofday(&stop_time, NULL);
    //gettimeofday(&start_time, NULL);
      
    this_time = SDL_GetTicks64();
    if (this_time >= last_time)
      {
      while ((last_time + FRAME_TIME) > this_time)
        {
        usleep(1000);
        this_time = SDL_GetTicks64();
        }
      }

    last_time = this_time;

    main_function_result = my_audio_window->draw_trace(return_audio_buffer,
    our_audio_trace_width); 
     
    // display fft only when the entire fft buffer is done
    if (return_spectrum_buffer != NULL)
      {
      main_function_result = my_spectrum_window->draw_trace(return_spectrum_buffer,
       our_spectrum_trace_width);
      }

    // Piano section
    piano_data_pointer = my_piano_process->process_piano_data(my_main_buffer);
    if (piano_data_pointer == NULL)
      {
      printf("piano not done\n");
      }
    else
      {
      printf ("piano done\n");
      my_piano_window->draw_trace(piano_data_pointer);        
      }
    }


  return main_function_result;
}
