#pragma once

#include "pxl8_types.h"

#define PXL8_ASE_MAGIC 0xA5E0
#define PXL8_ASE_FRAME_MAGIC 0xF1FA
#define PXL8_ASE_CHUNK_CEL 0x2005
#define PXL8_ASE_CHUNK_LAYER 0x2004
#define PXL8_ASE_CHUNK_OLD_PALETTE 0x0004
#define PXL8_ASE_CHUNK_PALETTE 0x2019
#define PXL8_ASE_CHUNK_TILESET 0x2023
#define PXL8_ASE_CHUNK_USER_DATA 0x2020

typedef struct pxl8_ase_header {
    u32 file_size;
    u16 magic;
    u16 frames;
    u16 width;
    u16 height;
    u16 color_depth;
    u32 flags;
    u16 speed;
    u32 transparent_index;
    u8 n_colors;
    u8 pixel_width;
    u8 pixel_height;
    i16 grid_x;
    i16 grid_y;
    u16 grid_width;
    u16 grid_height;
} pxl8_ase_header;

typedef struct pxl8_ase_frame_header {
    u32 frame_bytes;
    u16 magic;
    u16 chunks;
    u16 duration;
} pxl8_ase_frame_header;

typedef struct pxl8_ase_chunk_header {
    u32 chunk_size;
    u16 chunk_type;
} pxl8_ase_chunk_header;

typedef struct pxl8_ase_cel {
    u16 layer_index;
    i16 x;
    i16 y;
    u8 opacity;
    u16 cel_type;

    union {
        struct {
            u16 width;
            u16 height;
            u8* pixels;
        } image;

        struct {
            u16 width;
            u16 height;
            u16 bits_per_tile;
            u32 tile_id_mask;
            u32 x_flip_mask;
            u32 y_flip_mask;
            u32 diag_flip_mask;
            u32* tiles;
        } tilemap;
    };
} pxl8_ase_cel;

typedef struct pxl8_ase_layer {
    u16 flags;
    u16 layer_type;
    u16 child_level;
    u16 blend_mode;
    u8 opacity;
    char* name;
} pxl8_ase_layer;

typedef struct pxl8_ase_palette {
    u32 entry_count;
    u32 first_color;
    u32 last_color;
    u32* colors;
} pxl8_ase_palette;

typedef struct pxl8_ase_frame {
    u16 frame_id;
    u16 width;
    u16 height;
    i16 x;
    i16 y;
    u16 duration;
    u8* pixels;
    u32 cel_count;
    pxl8_ase_cel* cels;
} pxl8_ase_frame;

typedef struct pxl8_ase_property {
    char* name;
    u32 type;
    union {
        bool bool_val;
        i32 int_val;
        f32 float_val;
        char* string_val;
    };
} pxl8_ase_property;

typedef struct pxl8_ase_user_data {
    char* text;
    u32 color;
    bool has_color;
    bool has_text;
    u32 property_count;
    pxl8_ase_property* properties;
} pxl8_ase_user_data;

typedef struct pxl8_ase_tileset {
    u32 id;
    u32 flags;
    u32 tile_count;
    u16 tile_width;
    u16 tile_height;
    i16 base_index;
    char* name;
    u32 pixels_size;
    u8* pixels;
    pxl8_ase_user_data* tile_user_data;
} pxl8_ase_tileset;

typedef struct pxl8_ase_file {
    u32 frame_count;
    pxl8_ase_frame* frames;
    pxl8_ase_header header;
    u32 layer_count;
    pxl8_ase_layer* layers;
    pxl8_ase_palette palette;
    u32 tileset_count;
    pxl8_ase_tileset* tilesets;
} pxl8_ase_file;

#ifdef __cplusplus
extern "C" {
#endif

pxl8_result pxl8_ase_load(const char* filepath, pxl8_ase_file* ase_file);
void pxl8_ase_destroy(pxl8_ase_file* ase_file);

#ifdef __cplusplus
}
#endif
