#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "Popcorn:h.Popcorn"

_kernel_oserror err_returned;

_kernel_oserror *err(char *msg, int line, FILE *handle) {
  sprintf(err_returned.errmess, "LoadPrototype: %s (line %d).", msg, line);
  if (handle != NULL) fclose(handle);
  return &err_returned;
}

_kernel_oserror *Popcorn_LoadPrototypes(char *proto_filename) {
  FILE                *handle, *sprite_handle;
  char		      line[1024], filename[256], *variable = line, *value,
  		      *chk;
  int		      c, current_frame = 0, next_id = 0, frames = 0,
  		      line_num = 0, sx, sy, cx, cy, auto_centre;
  struct prototype    *cp = NULL;
  struct {
    int height, width;
  } sprite_header;


  handle = fopen(proto_filename, "rb");

  if (handle == NULL) {
    return(err("Couldn't open prototypes file", 0, NULL));
  }

  while (!feof(handle)) {

/* Get string from file, change LF terminator to zero byte */

    chk = fgets(line, 1024, handle);

    line_num++;
    for(c=0; line[c]>31; c++);
    line[c]=0;

 /* Sort out 'variable' and 'value', skip spaces and things... */

    if (line[0] != '#' && line[0] > 31 && chk != NULL) {
      c=0;
      while (line[c] != ' ') c++;
      line[c] = 0;
      while (line[c] != '=') c++;
      c++;
      while (line[c] == ' ') c++;
      value = &line[c];

      if (strcmp(variable, "id") == 0) {
        if (current_frame != frames ) {
          return(err("New prototype started without finishing all the frames of previous one", line_num, handle));
        }
        sscanf(value, "%s %d", &next_id, &frames); current_frame = 0;

/*         printf("%X %d frames\n", next_id, frames); */
        if ((prototype[prototype_free] = malloc(sizeof(struct prototype) +
          (sizeof(struct frame_data) * frames))) == NULL) {
          return(err("Couldn't allocate memory for prototype", line_num, handle));
        }
        cp = prototype[prototype_free]; /* Just shorthand... */
        prototype_free++;
        cp->id      = next_id; next_id = 0;
        cp->handler = NULL; cp->flags.word = 0;
        cp->animation.frames = frames;
        for (c=0; c!=frames; c++)
          cp->animation.frame[c].sprite_anchor = NULL;
      }

      if (strcmp(variable, "handler") == 0) {
        cp->handler = Popcorn_FindSymbol(value);
/*         printf("handler: %X\n", cp->handler); */
      }
      /* plot_offset flag added by Rik */
      if (strcmp(variable, "objflags") == 0) {
        if (strstr(value,"std_plot")!=0)     cp->flags.bits.std_plot     = TRUE;
        if (strstr(value,"plot_offset")!=0)  cp->flags.bits.plot_offset  = TRUE;
        if (strstr(value,"animate")!=0)      cp->flags.bits.animate      = TRUE;
        if (strstr(value,"collide")!=0)      cp->flags.bits.collide      = TRUE;
        if (strstr(value,"velocities")!=0)   cp->flags.bits.velocities   = TRUE;
        if (strstr(value,"gravity")!=0)      cp->flags.bits.gravity      = TRUE;
        if (strstr(value,"attn_every")!=0)   cp->flags.bits.attn_every   = TRUE;
        if (strstr(value,"attn_plot")!=0)    cp->flags.bits.attn_plot    = TRUE;
        if (strstr(value,"attn_timer")!=0)   cp->flags.bits.attn_timer   = TRUE;
        if (strstr(value,"attn_plotout")!=0) cp->flags.bits.attn_plotout = TRUE;
        if (strstr(value,"attn_gameout")!=0) cp->flags.bits.attn_gameout = TRUE;
        if (strstr(value,"attn_userout")!=0) cp->flags.bits.attn_userout = TRUE;
        if (strstr(value,"kill_timer")!=0)   cp->flags.bits.kill_timer   = TRUE;
        if (strstr(value,"kill_plotout")!=0) cp->flags.bits.kill_plotout = TRUE;
        if (strstr(value,"kill_gameout")!=0) cp->flags.bits.kill_gameout = TRUE;
        if (strstr(value,"kill_userout")!=0) cp->flags.bits.kill_userout = TRUE;
        if (strstr(value,"yoyo")!=0)         cp->flags.bits.yoyo         = TRUE;
/*         printf("flags: %X\n", cp->flags.word); */
      }

      if (strcmp(variable, "frame") == 0) {
        if (current_frame == frames) {
          return(err("Too many frames", line_num, handle));
        }

        auto_centre = sx = sy = cx = cy = -1;
        if (strstr(value, "S@") != 0)
          sscanf(strstr(value, "S@"), "S@%d,%d", &sx, &sy);
        if (strstr(value, "C@") != 0)
          sscanf(strstr(value, "C@"), "C@%d,%d", &cx, &cy);
        if (strstr(value, "auto_centre") != 0)
          sscanf(strstr(value, "auto_centre"), "auto_centre@%d", &auto_centre);

        sscanf(value, "%s ", filename);

        if (sx == -1) {
/*           printf("trying: %s\n", filename); */
          sprite_handle = fopen(filename, "rb");
          if (sprite_handle == NULL) {
            return(err("Couldn't open sprite file", line_num, handle));
          }
          fread(&sprite_header, 4, 2, sprite_handle);
          fclose(sprite_handle);
          sx = sprite_header.width  - 1;
          sy = sprite_header.height - 1;
        }

        if (cx == -1 && auto_centre == -1)
          auto_centre = 5;

        switch (auto_centre) {
          case 1 : cx=0; cy=0; break;
          case 2 : cx=(sx+1)>>1; cy=0; break;
          case 3 : cx=sx; cy=0; break;
          case 4 : cx=0; cy=(sy+1)>>1; break;
          case 5 : cx=(sx+1)>>1; cy=(sy+1)>>1; break;
          case 6 : cx=sx; cy=(sy+1)>>1; break;
          case 7 : cx=0; cy=sy; break;
          case 8 : cx=(sx+1)>>1; cy=sy; break;
          case 9 : cx=sx; cy=sy;
        }

        cp->animation.frame[current_frame].centre_x = cx;
        cp->animation.frame[current_frame].centre_y = cy;
        cp->animation.frame[current_frame].size_x = sx;
        cp->animation.frame[current_frame].size_y = sy;
        cp->animation.frame[current_frame].sprite_anchor = Popcorn_FindResource(filename);
/*         if (*(cp->animation.frame[current_frame].sprite_anchor) == NULL) */
/*           printf("NULL %s\n", filename); */

/*         printf("frame %d: S@%d,%d C@%d,%d %08X %s\n", current_frame, sx, sy, cx, cy, cp->animation.frame[current_frame].sprite_anchor, filename); */

        current_frame++;
      }
    }
  }
  fclose(handle);
  return NULL;
}
