#include <stdio.h>
#include "swis.h"
#include <kernel.h>
#include <time.h>
#include "Sound.h"

// SWI Registers
_kernel_swi_regs inreg;
_kernel_swi_regs outreg;

// Sprite buffer
unsigned char *buffer;

extern struct CompositionElement composition[128];
extern int current_element;

#define DISPLAY_MODE 28
#define DISPLAY_X 1280
#define DISPLAY_Y 960

#define PLAYER_Y_START 100
#define PLAYER_X_SPEED 10
#define MAX_NPCS 5
#define MAX_STARS 49

enum sprite_e{player_ship, durno_ship,player_shipl,player_shipr};
char *sprites[] = {"player_ship","durno_ship","player_shipl","player_shipr"};

int font = 0;

struct EntityLocation_s {
  short int X,Y;
};

struct NPC_s {
  struct EntityLocation_s location;
  enum sprite_e sprite;
  unsigned char velocity;
};

struct Player_s {
  struct EntityLocation_s location;
  enum sprite_e sprite;
  unsigned char velocity;
};

struct NPC_s NPCS[MAX_NPCS];
struct Player_s Player;
struct EntityLocation_s Stars[MAX_STARS];

int tick = 0;
int lasttick = 0;
extern int screen;
void intro()
{
  int currentstart = 0;

  sound_voices(4);

  sound_set_voice(1,"WaveSynth-Beep");
  sound_set_voice(2,"WaveSynth-Beep");
  sound_set_voice(3,"WaveSynth-Beep");
  sound_set_voice(4,"WaveSynth-Beep");
  sound_composition_init();
  
  // DUn, dun, daan duhhn
  sound_composition_element_add(currentstart,1,sound_note("A4#"),200);
  sound_composition_element_add(currentstart,2,sound_note("A5#"),200);
  currentstart += 200;
  sound_composition_element_add(currentstart,1,sound_note("F3"),200);
  sound_composition_element_add(currentstart,2,sound_note("F4"),200);
  currentstart += 200;
  sound_composition_element_add(currentstart,1,sound_note("G3#"),200);
  sound_composition_element_add(currentstart,2,sound_note("G4#"),200);
  currentstart += 200;
  sound_composition_element_add(currentstart,1,sound_note("C3"),200);
  sound_composition_element_add(currentstart,2,sound_note("C4"),200);
  currentstart += 200;

  // DUn, dun, daan duhhn
  sound_composition_element_add(currentstart,1,sound_note("A3#"),200);
  sound_composition_element_add(currentstart,2,sound_note("A4#"),200);
  currentstart += 200;
  sound_composition_element_add(currentstart,1,sound_note("F2"),200);
  currentstart += 200;
  sound_composition_element_add(currentstart,2,sound_note("G2#"),200);
  currentstart += 200;
  sound_composition_element_add(currentstart,1,sound_note("C2"),200);
  currentstart += 250;

  // Duh
  sound_composition_element_add(currentstart,3,sound_note("A3#"),300);
  sound_composition_element_add(currentstart,4,sound_note("A2#"),300);
  currentstart += 200;

  //REM Dun De Da
  sound_composition_element_add(currentstart,1,sound_note("F1"),20);
  currentstart += 50;
  sound_composition_element_add(currentstart,2,sound_note("A2#"),5);
  currentstart += 20;
  sound_composition_element_add(currentstart,1,sound_note("D2#"),200);
  currentstart += 180;


  sound_composition_element_add(currentstart,2,sound_note("D2"),50);
  currentstart += 50;
  sound_composition_element_add(currentstart,1,sound_note("A2#"),30);
  currentstart += 30;
  sound_composition_element_add(currentstart,2,sound_note("G1"),50);
  currentstart += 50;
  sound_composition_element_add(currentstart,1,sound_note("C2"),50);
  currentstart += 50;
  sound_composition_element_add(currentstart,3,sound_note("A2#"),100);
  sound_composition_element_add(currentstart,4,sound_note("F2"),100);
  currentstart += 100;
  
  draw_sprite("tng",320,400);
  sound_composition_start(clock());
  
  while(sound_composition_incomplete())
  {
    sound_composition_tick(clock());

    if(input_readkey(98))
      sound_composition_stop();
  }
}

void game_draw_player()
{
  draw_sprite(sprites[Player.sprite], Player.location.X, Player.location.Y);
}
void game_draw_stars()
{
  unsigned char i;
  for(i = 0; i <= MAX_STARS; i++)
  {
    draw_line(Stars[i].X,Stars[i].Y,Stars[i].X,Stars[i].Y+30);
  }
}

void game_setup_player()
{
  Player.location.X = DISPLAY_X/2;
  Player.location.Y = PLAYER_Y_START;
  Player.sprite = player_ship;
}

void game_tick_stars()
{
  unsigned char i;
  for(i = 0; i <= MAX_STARS; i++)
  {
    Stars[i].Y -= (tick - lasttick) * 2;
    if(Stars[i].Y <= 0)
    {
      Stars[i].X = rand() % DISPLAY_X;
      Stars[i].Y = DISPLAY_Y;
    }
  }
}

void game_setup_stars()
{
  unsigned char i;
  for(i = 0; i <= MAX_STARS; i++)
  {
    Stars[i].X = rand() % DISPLAY_X;
    Stars[i].Y = rand() % DISPLAY_Y;
  }
}

void game_setup_input()
{
  /*
    inreg.r[0] = 4;
  inreg.r[1] = 1;
  _kernel_swi(OS_Byte,&inreg,&outreg);
  */
}

void game_input_tick()
{
  // Right arrow
  if(input_readkey(121))
  {
    Player.location.X += PLAYER_X_SPEED * (tick - lasttick);
    Player.sprite = player_shipr;
    // TODO: SHIP WIDTH
    if(Player.location.X > DISPLAY_X)
    {
      Player.location.X = DISPLAY_X;
      Player.sprite = player_ship;
    }
  }

  // Left arrow
  if(input_readkey(25))
  {
    Player.location.X -= PLAYER_X_SPEED * (tick - lasttick);
    Player.sprite = player_shipl;
    if(Player.location.X < 0)
    {
      Player.location.X = 0;
      Player.sprite = player_ship;
    }
  }
}

void game_setup_audio()
{
  sound_voices(4);

  sound_set_voice(1,"WaveSynth-Beep");
  sound_set_voice(2,"Percussion-Noise");
  sound_set_voice(3,"Percussion-Soft");
  sound_set_voice(4,"Percussion-Noise");
}

void game_draw_hud()
{
  draw_sprite("lcars",4,DISPLAY_Y-180);

inreg.r[0] = font;
inreg.r[1] = (int)"Shields";
inreg.r[2] = 1 << 4;
inreg.r[3] = 75;
inreg.r[4] = DISPLAY_Y-60;
inreg.r[5] = 0;
inreg.r[6] = 0;
inreg.r[7] = 0;
_kernel_swi(Font_Paint,&inreg,&outreg);

inreg.r[0] = font;
inreg.r[1] = (int)"Integrity";
inreg.r[2] = 1 << 4;
inreg.r[3] = 75;
inreg.r[4] = DISPLAY_Y-90;
inreg.r[5] = 0;
inreg.r[6] = 0;
inreg.r[7] = 0;
_kernel_swi(Font_Paint,&inreg,&outreg);

inreg.r[0] = font;
inreg.r[1] = (int)"Velocity";
inreg.r[2] = 1 << 4;
inreg.r[3] = 75;
inreg.r[4] = DISPLAY_Y-120;
inreg.r[5] = 0;
inreg.r[6] = 0;
inreg.r[7] = 0;
_kernel_swi(Font_Paint,&inreg,&outreg);

inreg.r[0] = font;
inreg.r[1] = (int)"Distance";
inreg.r[2] = 1 << 4;
inreg.r[3] = 75;
inreg.r[4] = DISPLAY_Y-150;
inreg.r[5] = 0;
inreg.r[6] = 0;
inreg.r[7] = 0;
_kernel_swi(Font_Paint,&inreg,&outreg);
}

void game_setup()
{
  game_setup_input();
  game_setup_audio();
  game_setup_stars();
  game_setup_player();
  tick = clock();
}

void game_tick()
{
  lasttick = tick;
  tick = clock();

  screen_flipbuffer();
  screen_clear();

  game_tick_stars();
  game_input_tick();
  
  game_draw_stars();
  game_draw_player();
  
  game_draw_hud();
}

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

  display_mode(DISPLAY_MODE);
  load_sprites("Spr");

  //intro();

  display_mode(DISPLAY_MODE);

inreg.r[0] = 0;
inreg.r[1] = (int)"System.Medium";
inreg.r[2] = 12*16;
inreg.r[3] = 8*16;
inreg.r[4] = 0;
inreg.r[5] = 0;
_kernel_swi(Font_FindFont,&inreg,&outreg);

font = outreg.r[0];
inreg.r[0] = 0;
inreg.r[1] = 0xffaaa000; // TODO: Not purple
inreg.r[2] = 0x11111000;
inreg.r[3] = 14;
_kernel_swi(ColourTrans_SetFontColours, &inreg, &outreg);

  game_setup();
  
  while(1)
    game_tick();
  free(buffer);

  return 0;
}
