#ifndef TRUE
#define TRUE (0==0)
#define FALSE (0!=0)
#endif

#include "spritelib.h"

#include "ship_animation.h"
#include "my_sprites.h"

#ifndef FONT_ASTEROIDS
#define FONT_HERSHEY 1
#define FONT_ASTEROIDS 2
#define FONT_PROTEL 3
#endif

int box(void) {
   // everything in here is drawn 'on the fly', not from a stored data
   int i = 0;
   drawline(   1,    1,    1, 255, FALSE, TRUE);
   drawline(   1,  255,  255, 255,  TRUE, TRUE);
   drawline( 255,  255,  255,   1, FALSE, FALSE);
   drawline( 255,    1,    1,   1,  TRUE, FALSE);
   return i;
}

int cross(void) {
   // everything in here is drawn 'on the fly', not from a stored data
   int i = 0;
   drawline(   1,    1,  255, 255, FALSE, TRUE);
   drawline(   1,  255,  255,   1, FALSE, FALSE);
   return i;
}

#include "my_graphics.h"

// This is called once per frame to do all internal logic and to position graphics
// ready for drawing.  IT DOES NOT draw anything at all itself.

void do_frame(void) {
#define BOUND 100
  static int init = 0;
  // NOTE: declarations must be static or they are reset between frames
  static int CB1, CB2, Queen0, Queen1, Queen2, Queen3, Ship0;
  static int y=0, x=0, dx=-3, dy=2;
  static int tick=0;
  static int skin=0;

  if (!init) {
    init = 1;

    // Positioning scale for objects is currently hard-coded as 127 - to be improved?
    // Other scales are per-object

    // Create and enable your sprites:
    //CB1 = Post((Object *)&draw_box, 0, 0, 0);
    (void)CB1;
    //CB2 = Post((Object *)&draw_cross, 0, 0, 0);
    //Queen0 = Post((Object *)&Queen[0], x, y, SCALE*3);
    //Queen1 = Post((Object *)&Queen[1], y, x, SCALE*3);
    // Queen3 is not posted at startup
    //Queen2 = Post((Object *)&Queen[2], 64, 64, SCALE*3);
    (void)Queen2;

    //Ship0 = Post((Object *)&Ship, 0, 0, 0x10);

  }
  // Move a sprite. Calculation here could be quite expensive, such as calculating the
  // move in a chess engine, or the perspective rendering in DOOM.

  { unsigned int dir;
    y += dy;
    if (abs(y) > BOUND) {
      dy = -dy;
      if ((dy>=0) && (dx>=0)) dir = 32U;
      if ((dy<0) && (dx>=0)) dir = 96U;
      if ((dy<0) && (dx<0)) dir = 160U;
      if ((dy>=0) && (dx<0)) dir = 224U;
      Direction(Queen1, dir);
    }
    x += dx;
    if (abs(x) > BOUND) {
      dx = -dx;
      if ((dy>=0) && (dx>=0)) dir = 32U;
      if ((dy<0) && (dx>=0)) dir = 96U;
      if ((dy<0) && (dx<0)) dir = 160U;
      if ((dy>=0) && (dx<0)) dir = 224U;
      Direction(Queen1, dir);
    }
  }

  Move(Queen0, x, y); // Moving and automatically rotating sprite
  Move(Queen1, y, x); // Moving sprite
  // Move(Queen2, 64, 64); // Doesn't move, but does rotate automatically

  Brightness(Ship0, 0U+(tick & 128U ? tick&127U : 127-(tick&127U))); // Pulse brightness

  if (((tick+64) & 127) == 127) {
    // Appears:
    //Queen3 = Post((Object *)&Queen[3], -64, -64, SCALE*2);
    Unpost(CB2); // must have been posted in init code
  } else if ((tick & 127) == 127) {
    Unpost(Queen3); // Disappears. Doesn't move or rotate.
    //CB2 = Post((Object *)&draw_cross, 0, 0, 0);
  }
  // The tailgunner ship is not actually rotating, it is cycling through 24 different
  // static skins. (It was the only animation I had handy, not the best demo, sorry)
  if (tick&2) { skin = (skin+1) % 24; Ship.data->data = (signed char *)ShipSkins[skin]; }

  tick++;
}

// This is a standard 'main program' loop, but the code above
// should also work with an interrupt-driven main loop...
// We'll supply the interrupt-driven version after the library
// interface has stabilised... (currently very much under development)
extern void
draw_string(
     int font,
	const char * s,
	int x,
	int y,
     int move_scale,
     int draw_scale
);

int main(void /* int argc, char **argv */) {
  static char s[3];
  char c='A', tick=0;
  s[0] = c; s[1] = c+1; s[2] = '\0';
  for (;;) {
    do_frame();
    Intensity_7F();

    //draw_string(FONT_HERSHEY,   s,  -120, 100,   127,105); 
    //draw_string(FONT_ASTEROIDS, s,  -70, 83,     127,127); 
    draw_string(FONT_PROTEL,    "Sprites",  -95, 50,     127,30); 

    if ((tick&63) == 63) {
      c++; if (c == 126) c = 32; s[0] = c; s[1] = c+1;
    }
    tick++;
    UpdateDisplay();
  }
  return 0;
}