#ifndef _SPRITE_H_
#define _SPRITE_H_

#include <box2d/box2d.h>
#include <tidwall/hashmap.h>

#define SPRITE_MAX_FRAMES                 16
#define SPRITE_MAX_NAME_LENGTH            128
#define SPRITE_MAX_REGISTRY_SIZE          1024
#define SPRITE_SHEET_MAX_FILENAME_LENGTH  512
#define SPRITE_MAX_ACTOR_NAME_LENGTH      128

typedef struct {
  SDL_Texture *texture;
  char sourcefile[SPRITE_SHEET_MAX_FILENAME_LENGTH];
  short sprite_w;
  short sprite_h;
} spritesheet;

typedef struct {
  spritesheet *sheet;
  short frameids[SPRITE_MAX_FRAMES]; // which IDs on the spritesheet belong to our frames
  short frames; // how many frames are in this animation
  short width;
  short height;
  short speed; // how many milliseconds a given sprite frame should be visible before cycling
  bool loop; // when this sprite is done playing, it should immediately start again
  bool loopReverse; // when this sprite is done playing, it should go in reverse order through its frames
  char name[SPRITE_MAX_NAME_LENGTH];
} sprite;

typedef struct {
  char name[SPRITE_MAX_ACTOR_NAME_LENGTH];
  sprite *curSprite;
  short curSpriteFrameId;
  SDL_Time curSpriteFrameTimer;
  bool curSpriteReversing;
  short layer;
  b2BodyId physicsId;
  b2Polygon physicsBox;
  int state;
  void *actorData;
  int x;
  int y;
} actor;

extern struct hashmap *registry_sprite;
extern struct hashmap *registry_actor;
extern struct hashmap *registry_spritesheet;

void registry_init(void);
void actor_new(actor *obj, char *name);
void actor_set_sprite(actor *obj, char *sprite_name);
void actor_render(actor *obj, SDL_Renderer *renderer);
void actor_update(actor *obj);
// initializes a new sprite to use the given sheet and otherwise sets to zero
void sprite_new(sprite *spr, char *name, spritesheet *sheet);
// loads a given image file into a new spritesheet
void spritesheet_new(spritesheet *sheet, short sprite_w, short sprite_h, char *filename);


#endif //_SPRITE_H_
