// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef _ALIAS_UI_H_
#define _ALIAS_UI_H_

#include <stdarg.h>

#include <alias/color.h>
#include <alias/memory.h>

#ifndef ALIAS_UI_INDEX_SIZE
#define ALIAS_UI_INDEX_SIZE 16
#endif

typedef struct alias_ui alias_ui;

typedef enum alias_ui_Result { alias_ui_Success, alias_ui_ErrorOutOfMemory } alias_ui_Result;

struct alias_ui_Font_GlyphInfo {
  bool newline;
  float advance_x;
  float x;
  float y;
  float width;
  float height;
  float s0;
  float t0;
  float s1;
  float t1;
};

struct alias_ui_Font {
  struct alias_ui_Font *fallback;
  uint32_t texture_id;
  bool (*decode)(struct alias_ui_Font *font, const char *string, uint32_t *inout_glyph, uint32_t *out_num_bytes,
                 struct alias_ui_Font_GlyphInfo *out_info);
  void *user_data;
};

typedef struct alias_ui_Size {
  float width;
  float height;
} alias_ui_Size;

typedef struct alias_ui_Constraint {
  alias_ui_Size min;
  alias_ui_Size max;
} alias_ui_Constraint;

void alias_ui_set_texture(struct alias_ui *ui, uint32_t texture_id);
void alias_ui_draw_rectangle(struct alias_ui *ui, float x, float y, float width, float height,
                                                     float s0, float t0, float s1, float t1, uint8_t r, uint8_t g,
                                                     uint8_t b, uint8_t a);

typedef void (*alias_ui_TextSizeFn)(alias_ui *ui, const char *buffer, float size, float max_width, float *out_width, float *out_height);
typedef void (*alias_ui_TextDrawFn)(alias_ui *ui, const char *buffer, float x, float y, float width, float size, alias_Color color);

typedef struct alias_ui_Input {
  alias_ui_Size screen_size;

  alias_ui_TextSizeFn text_size;
  alias_ui_TextDrawFn text_draw;
} alias_ui_Input;

typedef struct alias_ui_OutputGroup {
  uint32_t texture_id;
  uint32_t index;
  uint32_t length;
} alias_ui_OutputGroup;

typedef struct alias_ui_Output {
  uint32_t num_groups;
  uint32_t max_groups;
  alias_ui_OutputGroup *groups;

  uint32_t num_indexes;
  alias_memory_SubBuffer index_sub_buffer;

  uint32_t num_vertexes;
  alias_memory_SubBuffer xy_sub_buffer;
  alias_memory_SubBuffer rgba_sub_buffer;
  alias_memory_SubBuffer st_sub_buffer;
} alias_ui_Output;

// lifetime
alias_ui_Result alias_ui_initialize(alias_MemoryCB *mcb, alias_ui **ui_ptr);
void alias_ui_free(alias_ui *ui, alias_MemoryCB *mcb);

// frame
alias_ui_Result alias_ui_begin_frame(alias_ui *ui, alias_MemoryCB *mcb, const alias_ui_Input *input);
alias_ui_Result alias_ui_end_frame(alias_ui *ui, alias_MemoryCB *mcb, alias_ui_Output *output);

alias_ui_Result alias_ui_add_font(struct alias_ui *ui, struct alias_ui_Font *font, uint32_t *out_result);

// layouting
void alias_ui_align(alias_ui *ui, float x, float y);
void alias_ui_align_x(alias_ui *ui, float x);
void alias_ui_align_y(alias_ui *ui, float y);

void alias_ui_size(alias_ui *ui, float width, float height);
void alias_ui_width(alias_ui *ui, float width);
void alias_ui_height(alias_ui *ui, float height);

void alias_ui_margin(alias_ui *ui, float left, float right, float top, float bottom);
void alias_ui_padding(alias_ui *ui, float left, float right, float top, float bottom);

void alias_ui_begin_stack(alias_ui *ui);
void alias_ui_begin_vertical_stack(alias_ui *ui);
void alias_ui_begin_horizontal_stack(alias_ui *ui);
void alias_ui_end_stack(alias_ui *ui);
void alias_ui_stats(alias_ui *ui, uint32_t *num_vertexes, uint32_t *num_indexes, uint32_t *num_groups);

// per scope parameters
void alias_ui_font_size(alias_ui *ui, float size);
void alias_ui_font_color(alias_ui *ui, alias_Color color);

// create elements
void alias_ui_textv(alias_ui *ui, const char *format, va_list ap);
void alias_ui_color_fill(alias_ui *ui, float r, float g, float b, float a);
void alias_ui_image(alias_ui *ui, float width, float height, float s0, float t0, float s1, float t1, uint32_t texture_id);

static inline void alias_ui_text(alias_ui *ui, const char *format, ...) {
  va_list ap;
  va_start(ap, format);
  alias_ui_textv(ui, format, ap);
  va_end(ap);
}

#endif