#include <stdio.h>
#include <SDL2/SDL.h>

#define LCR_SETTING_LOG_LEVEL 2

#define DATA_FILE_NAME "data"

#include "game.h"

SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *texture;
SDL_Surface *screenSurface;
uint16_t screen[LCR_SETTING_RESOLUTION_X * LCR_SETTING_RESOLUTION_Y];

FILE *musicFile = 0;
FILE *dataFile = 0;

char LCR_getNextDataFileChar(void)
{
  if (!dataFile)
    return 0;

  int c = fgetc(dataFile);

  if (c == EOF)
  {
    rewind(dataFile);
    return 0;
  }

  return c;
}

void LCR_appendDataStr(const char *str)
{
  if (!dataFile)
    return;

  if (*str == 0)
    rewind(dataFile);
  else
  {
    fclose(dataFile);
    
    dataFile = fopen(DATA_FILE_NAME,"a");
    
    if (dataFile)
    {
      fprintf(dataFile,"%s",str);
      fclose(dataFile);
      dataFile = fopen(DATA_FILE_NAME,"r");
    }
  }
}

void audioFillCallback(void *userdata, uint8_t *s, int l)
{
  if (musicFile && LCR_gameMusicOn())
  {
    if (!fread(s,1,l,musicFile))
      rewind(musicFile);
  }
  else
    for (int i = 0; i < l; ++i)
      s[i] = 128;

  for (int i = 0; i < l; ++i)
    s[i] = s[i] / 2 + LCR_gameGetNextAudioSample() / 2;
}

const uint8_t *keyboardState;

uint8_t LCR_keyPressed(uint8_t key)
{
  switch (key)
  {
    case LCR_KEY_UP: return
      keyboardState[SDL_SCANCODE_W] | keyboardState[SDL_SCANCODE_UP]; break;

    case LCR_KEY_RIGHT: return
      keyboardState[SDL_SCANCODE_D] | keyboardState[SDL_SCANCODE_RIGHT]; break;

    case LCR_KEY_DOWN: return
      keyboardState[SDL_SCANCODE_S] | keyboardState[SDL_SCANCODE_DOWN]; break;

    case LCR_KEY_LEFT: return
      keyboardState[SDL_SCANCODE_A] | keyboardState[SDL_SCANCODE_LEFT]; break;

    case LCR_KEY_A: return
      keyboardState[SDL_SCANCODE_K] | keyboardState[SDL_SCANCODE_RETURN]; break;

    case LCR_KEY_B: return
      keyboardState[SDL_SCANCODE_L] | keyboardState[SDL_SCANCODE_ESCAPE]; break;

    default: break;
  }

  return 0;
}

void LCR_sleep(uint16_t timeMs)
{
  usleep(timeMs * 1000);
}

void LCR_drawPixel(unsigned long index, uint16_t color)
{
  screen[index] = color;
}

void LCR_log(const char *str)
{
  printf("LOG: %s\n",str);
}

int main(int argc, char *argv[])
{
  uint8_t running = 1;

  dataFile = fopen(DATA_FILE_NAME,"r");

  if (!dataFile)
    LCR_log("couldn't open data file");

  LCR_log("initializing game");
  LCR_gameInit(argc,(const char **) argv);

  LCR_log("initializing SDL");
  SDL_Init(SDL_INIT_AUDIO);

  LCR_log("initializing audio");
  SDL_AudioSpec audioSpec;
  SDL_memset(&audioSpec, 0, sizeof(audioSpec));
  audioSpec.callback = audioFillCallback;
  audioSpec.freq = 8000;
  audioSpec.format = AUDIO_U8;
  audioSpec.channels = 1;
  audioSpec.samples = 64;

  if (SDL_OpenAudio(&audioSpec,NULL) < 0)
    fputs("could not initialize audio",stderr);
    
  SDL_PauseAudio(0);

  musicFile = fopen("assets/music","rb");

  if (!musicFile)
    fputs("could not open music file",stderr);

  window =
    SDL_CreateWindow("Licar", SDL_WINDOWPOS_UNDEFINED,
    SDL_WINDOWPOS_UNDEFINED, LCR_SETTING_RESOLUTION_X, LCR_SETTING_RESOLUTION_Y,
    SDL_WINDOW_SHOWN); 

  if (!window)
  {
    fputs("ERROR: couldn't create window",stderr);
    return 1;
  }

  renderer = SDL_CreateRenderer(window,-1,0);

  if (!renderer)
  {
    fputs("ERROR: couldn't create renderer",stderr);
    return 1;
  }

  texture =
    SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGB565,SDL_TEXTUREACCESS_STATIC,
    LCR_SETTING_RESOLUTION_X,LCR_SETTING_RESOLUTION_Y);

  if (!texture)
  {
    fputs("ERROR: couldn't create texture",stderr);
    return 1;
  }

  screenSurface = SDL_GetWindowSurface(window);

  SDL_ShowCursor(0);

  SDL_PumpEvents();
  keyboardState = SDL_GetKeyboardState(NULL);

  LCR_log("starting game loop");

  while (running)
  {
    SDL_PumpEvents();
    keyboardState = SDL_GetKeyboardState(NULL);
    running = !keyboardState[SDL_SCANCODE_Q];

    running &= LCR_gameStep(SDL_GetTicks());

    SDL_UpdateTexture(texture,NULL,screen,
      LCR_SETTING_RESOLUTION_X * sizeof(uint16_t));

    SDL_RenderClear(renderer);
    SDL_RenderCopy(renderer,texture,NULL,NULL);
    SDL_RenderPresent(renderer);
  }

  LCR_log("ending");

  if (musicFile)
    fclose(musicFile);

  if (dataFile)
    fclose(dataFile);

  SDL_PauseAudio(1);
  SDL_CloseAudio();

  SDL_DestroyTexture(texture);
  SDL_DestroyRenderer(renderer); 
  SDL_DestroyWindow(window); 

  LCR_gameEnd();

  return 0;
}
