#ifndef SCOPE
#define SCOPE
#include <pulse/simple.h>
#include <pulse/error.h>
#include <fftw3.h>


#define SAMPLE_RATE 44100
#define FRAME_TIME 17
// this must be in power of 2 for fourier transform
#define READ_BUFFER_SIZE 2048
#define FFT_NUMBER_READ_BUFFERS 4 
#define FFT_BUFFER_SIZE (READ_BUFFER_SIZE * FFT_NUMBER_READ_BUFFERS)
#define MAIN_BUFFER_SIZE 8192
#define AUDIO_BUFFER_SIZE 6000
#define FFT_START_BUCKET 0
#define MAIN_VOLUME .1
#define SPECTRUM_VOLUME .1
#define PIANO_SIZE_MULTIPLY .65
#define KEYBOARD_POSITION_X 50
#define KEYBOARD_POSITION_Y 10
#define OCTIVE_POSITION_X 800
#define OCTIVE_POSITION_Y 10
#define NUMBER_KEY_LIGHTS 12
#define NUMBER_OCTIVE_LIGHTS 8
#define RADIANS_PER_SAMPLE_AT_1_HZ (double)6.28319/(double)SAMPLE_RATE
#define NUMBER_OCTIVES 6
#define BUCKETS_PER_NOTE 2
#define NOTES_PER_OCTIVE 12
#define BUCKETS_PER_OCTIVE BUCKETS_PER_NOTE*NOTES_PER_OCTIVE
#define TOTAL_BUCKETS BUCKETS_PER_OCTIVE*NUMBER_OCTIVES
#define TOTAL_NOTES NOTES_PER_OCTIVE*NUMBER_OCTIVES
#define Q_QUALITY 6
#define FIRST_FREQUENCY 32
#define PIANO_FULL_ARRAY_SIZE 10000

//Structure for piano notes
struct piano_note_struct {
double note_strength;
int keyboard_key;
int octive;;
};

//Structure for processing buckets
struct bucket_data_struct {
double bucket_frequency;
double bucket_strength;
int buffer_size;
double radians_per_sample;
struct piano_note_struct *this_piano_note;
};

// Structure used by both piano and main classes
struct piano_data_struct {
int keyboard_key;
int octive;
int done;
};

class main_window_class {
   public:
     main_window_class (int x_main_window_size, int y_main_window_size);

   private:
     SDL_Window *window_for_main;
     SDL_Renderer *renderer_for_main;
     int call_result;

};

class audio_window_class {

   public:
     audio_window_class (int x_main_window_size, int y_main_window_size);
     int draw_trace(int *audio_data, int audio_data_size);
     int get_max_audio_trace_width();
     int get_max_audio_trace_height();
     
   private:
     int x_audio_window_position;
     int y_audio_window_position;
     int x_audio_window_size;
     int y_audio_window_size;
     int x_audio_window_trace_base;
     int y_audio_window_trace_base;
     int max_audio_trace_width;
     int max_audio_trace_height;
     SDL_Window *window_for_audio;
     SDL_Renderer *renderer_for_audio;
     SDL_Rect rect_for_audio;
     SDL_Texture *texture_for_audio;
     SDL_Surface *surface_for_audio;
     TTF_Font *font_for_audio;
     SDL_Color color_for_audio;
};

class spectrum_window_class {

   public:
     spectrum_window_class (int x_main_window_size, int y_main_window_size);
     int draw_trace(int *spectrum_data, int spectrum_data_size);
     int get_max_spectrum_trace_width();
     int get_max_spectrum_trace_height();
     
   private:
     int x_spectrum_window_position;
     int y_spectrum_window_position;
     int x_spectrum_window_size;
     int y_spectrum_window_size;
     int x_spectrum_window_trace_base;
     int y_spectrum_window_trace_base;
     int max_spectrum_trace_width;
     int max_spectrum_trace_height;
     SDL_Window *window_for_spectrum;
     SDL_Renderer *renderer_for_spectrum;
     SDL_Rect rect_for_spectrum;
     SDL_Texture *texture_for_spectrum;
     SDL_Surface *surface_for_spectrum;
     TTF_Font *font_for_spectrum;
     SDL_Color color_for_spectrum;
};

class piano_window_class {

   public:
     piano_window_class (int x_main_window_size, int y_main_window_size);
     int draw_trace(piano_data_struct *input_piano_data);
     int get_max_piano_trace_width();
     int get_max_piano_trace_height();
     
   private:
     const char* keyboard_lights[12] = {
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key1.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key2.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key3.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key4.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key5.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key6.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key7.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key8.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key9.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key10.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key11.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/keyboard-key12.bmp"};

     const char* octive_lights[8] = {
       "/home/maallyn/sound-scope/sdl2/fft/octive-1.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/octive-2.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/octive-3.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/octive-4.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/octive-5.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/octive-6.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/octive-7.bmp",
       "/home/maallyn/sound-scope/sdl2/fft/octive-8.bmp"};

     struct piano_data_struct *my_piano_data;
     int x_piano_window_position;
     int y_piano_window_position;
     int x_piano_window_size;
     int y_piano_window_size;
     int x_piano_window_trace_base;
     int y_piano_window_trace_base;
     int max_piano_trace_width;
     int max_piano_trace_height;
     int function_result;
     int loop_counter;
     SDL_Window *window_for_piano;
     SDL_Renderer *renderer_for_piano;
     SDL_Rect rect_for_piano_text;
     SDL_Texture *texture_for_piano;
     SDL_Surface *surface_for_piano_text;
     SDL_Surface *surface_key_blank;
     SDL_Surface *surface_keys[12];
     SDL_Surface *surface_octive_blank;
     SDL_Surface *surface_octives[8];
     SDL_Texture *texture_key_blank;
     SDL_Texture *texture_keys[12];
     SDL_Texture *texture_octive_blank;
     SDL_Texture *texture_octives[8];
     SDL_Texture *texture_current_piano_light;
     SDL_Texture *texture_current_octive_light;
     SDL_Rect rect_for_keys;
     SDL_Rect rect_for_octives;

     TTF_Font *font_for_piano;
     SDL_Color color_for_piano;
     SDL_Rect rect_for_piano_image;
     SDL_Surface *piano_image_surface;
     SDL_Texture *texture_of_piano_image;
};

class main_buffer_manager_class {
  public:
    main_buffer_manager_class();
    ~main_buffer_manager_class();
    Sint16 *initial_preparation();
    Sint16 *read_main_buffer();

  private:
     Sint16 *my_read_main_buffer;
     int pulse_error;    
     int function_return;
     pa_simple *pulse_s = NULL;
     int main_buffer_index;
     Sint16 main_buffer_hold;
  };
  
class audio_buffer_manager_class {
  public:
     audio_buffer_manager_class();
     ~audio_buffer_manager_class();
     int initialize_audio(int horizontal_size,int vertical_size, Sint16 *main_buffer);
     int *process_audio();

  private:
     Sint16 *my_main_buffer;
     int *my_formatted_audio_buffer;
     int my_audio_horizontal_size;
     int my_audio_vertical_size;
     int my_read_audio_index;
     int function_return;
     Sint16 audio_holding;
  };

class spectrum_buffer_manager_class {
  public:
     spectrum_buffer_manager_class();
     ~spectrum_buffer_manager_class();
     int initialize_spectrum(int horizontal_size,int vertical_size, Sint16 *main_buffer);
     int *process_spectrum();

  private:
     Sint16 *my_main_buffer;
     int *my_formatted_spectrum_buffer;
     int my_spectrum_horizontal_size;
     int my_spectrum_vertical_size;
     int my_read_spectrum_index;
     int my_output_fft_buffer_index;
     int function_return;
     int read_buffer_counter;
     Sint16 spectrum_holding;
     fftw_plan my_fftw_plan;
     double *input_fftw;
     double *input_fftw_write_position;
     Sint16 main_buffer_hold;
     fftw_complex *output_fftw;
  };

class piano_process_class {
   public:
     piano_process_class();
     ~piano_process_class();
     int initialize_piano_data();
     struct piano_data_struct *process_piano_data(Sint16 *input_buffer);
     double goertzel(int num_samples, int target_frequency, int sample_rate, Sint16 *input_buffer);

   private:
     struct piano_data_struct my_piano_data_struct;
     Sint16 *local_main_buffer;
     int ctr1;
     struct piano_note_struct my_piano_notes[TOTAL_NOTES];
     struct bucket_data_struct my_bucket_data[TOTAL_BUCKETS];
     Sint16 full_size_buffer[PIANO_FULL_ARRAY_SIZE];
     int main_buffer_read_count;

 };
#endif
