/**
 * @file intro.c
 *
 * @brief Handle the introduction sequence.
 *
 * @todo Allow handling of images and other fancy things once we get them.
 */

#include <string.h>
#include "SDL.h"
#include "lephisto.h"
#include "log.h"
#include "pack.h"
#include "font.h"
#include "music.h"
#include "intro.h"

#define INTRO_FONT_SIZE 18. /**< Intro text font size. */
#define INTRO_SPEED     30. /**< Speed of text in characters / seconds. */

/* Intro text lines. */
static char** intro_lines = NULL; /**< Introduction text lines. */
static int intro_nlines = 0;      /**< Number of introduction text lines. */
static int intro_length = 0;      /**< Length of the text. */
static glFont intro_font;         /** Introduction font. */

static int intro_load(void);
static void intro_cleanup(void);

static int intro_load(void) {
  uint32_t intro_size;
  char* intro_buf;
  int i, p, n;
  int mem;

  intro_buf = pack_readfile(DATA, "../dat/intro", &intro_size);
  intro_length = intro_size; /* Length aproximation! */

  /* Create intro font. */
  gl_fontInit(&intro_font, NULL, INTRO_FONT_SIZE);

  /* Load lines. */
  p = 0;
  n = 0;
  mem = 0;
  while((uint32_t)p < intro_size) {
    /* Get the length. */
    i = gl_printWidthForText(&intro_font, &intro_buf[p], SCREEN_W - 200.);

    /* Copy the line. */
    if(n+1 > mem) {
      mem += 128;
      intro_lines = realloc(intro_lines, sizeof(char*) * mem);
    }
    intro_lines[n] = malloc(i+1);
    strncpy(intro_lines[n], &intro_buf[p], i);
    intro_lines[n][i] = '\0';

    p += i + 1; /* Move pointer. */
    n++; /* New line. */
  }
  /* Clean up. */
  free(intro_buf);

  intro_nlines = n;
  return 0;
}

/**
 * @brief Cleans up the intro crap!
 */
static void intro_cleanup(void) {
  int i;

  /* Free memory. */
  for(i = 0; i < intro_nlines; i++)
    free(intro_lines[i]);
  free(intro_lines);
  gl_freeFont(&intro_font);

  /* Set default. */
  intro_lines = NULL;
  intro_nlines = 0;
}

/**
 * @brief Display the introduction sequence.
 */
int intro_display(void) {
  int i, max;
  unsigned int tcur, tlast;
  double dt;
  double x, y, vel;
  double offset;
  double density;
  SDL_Event event;

  /* Load the introduction. */
  if(intro_load() < 0)
    return -1;

  /* Calculate velocity. */
  density = ((double)intro_length / (double)intro_nlines); /* char / line. */
  density /= (double)intro_font.h; /* char / pixel. */
  vel = INTRO_SPEED / density; /* (char / s) * (pixel / char) = pixel / s */

  /* Change music to intro music. */
  music_load("intro");
  music_play();

  /* Prepare for intro loop. */
  x = 100.;
  y = 0.;
  tlast = SDL_GetTicks();
  offset = 0.;
  /*offset = -(intro_font.h + 5.);*/
  max = intro_nlines + SCREEN_H / ((intro_font.h + 5.));

  while(1) {
    /* Get delta tick in seconds! */
    tcur = SDL_GetTicks();
    dt = (double)(tcur - tlast) / 1000.;
    tlast = tcur;

    /* Handle events. */
    while(SDL_PollEvent(&event)) {
      switch(event.type) {
        case SDL_KEYDOWN:
          /* Skip the boring intro we saw a million times already! */
          if(event.key.keysym.sym == SDLK_ESCAPE)
            offset = max * (intro_font.h + 5.);
          else if(!isspace(event.key.keysym.sym))
            break;
          /* Purpose fallthrough. */
        case SDL_JOYBUTTONDOWN:
          offset += 250.;
        default:
          break;
      }
    }

    /* Increment position. */
    offset += vel * dt;

    /* Clear stuff. */
    glClear(GL_COLOR_BUFFER_BIT);

    /* Draw text! */
    i = (int)(offset / (intro_font.h + 5.));
    if(i > max) /* Out of lines. */
      break;
    y = offset - (i+1) * (intro_font.h + 5.);

    while(i >= 0) {
      /* Skip in line isn't valid. */
      if(i >= intro_nlines) {
        i--;
        y += intro_font.h + 5.;
        continue;
      }

      gl_print(&intro_font, x, y, &cConsole, intro_lines[i]);

      /* Increment line and position. */
      i--;
      y += intro_font.h + 5.;
    }

    /* Display our sh*t. */
    SDL_GL_SwapBuffers();

    SDL_Delay(10); /* No need to go burning our CPU now! */
  }

  /* Stops music, normal music will start shortly after. */
  music_stop();
  
  /* Cleanup our mess. */
  intro_cleanup();

  return 0;
}

