// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)

//- rjf: stack table

@table(name, name_lower, type, default)
UI_StackTable:
{
  //- rjf: parents
  { Parent                             parent                       `UI_Box *`      `&ui_g_nil_box`    }
  
  //- rjf: layout params
  { ChildLayoutAxis                    child_layout_axis             Axis2          `Axis2_X`          }
  
  //- rjf: size/position
  { FixedX                             fixed_x                       F32            0                  }
  { FixedY                             fixed_y                       F32            0                  }
  { FixedWidth                         fixed_width                   F32            0                  }
  { FixedHeight                        fixed_height                  F32            0                  }
  { PrefWidth                          pref_width                    UI_Size        `ui_px(250.f, 1.f)`}
  { PrefHeight                         pref_height                   UI_Size        `ui_px(30.f, 1.f)` }
  
  //- rjf: flags
  { Flags                              flags                         UI_BoxFlags    0                  }
  
  //- rjf: interaction
  { FocusHot                           focus_hot                     UI_FocusKind   UI_FocusKind_Null  }
  { FocusActive                        focus_active                  UI_FocusKind   UI_FocusKind_Null  }
  { FastpathCodepoint                  fastpath_codepoint            U32            0                  }
  
  //- rjf: colors
  { Transparency                       transparency                  F32            0                  }
  { BackgroundColor                    background_color              Vec4F32        `v4f32(1, 0, 1, 1)`}
  { TextColor                          text_color                    Vec4F32        `v4f32(1, 0, 1, 1)`}
  { BorderColor                        border_color                  Vec4F32        `v4f32(1, 0, 1, 1)`}
  { OverlayColor                       overlay_color                 Vec4F32        `v4f32(1, 0, 1, 1)`}
  { TextSelectColor                    text_select_color             Vec4F32        `v4f32(1, 0, 1, 1)`}
  { TextCursorColor                    text_cursor_color             Vec4F32        `v4f32(1, 0, 1, 1)`}
  
  //- rjf: squish
  { Squish                             squish                        F32            0                  }
  
  //- rjf: hover cursor
  { HoverCursor                        hover_cursor                  OS_Cursor      OS_Cursor_Pointer  }
  
  //- rjf: font
  { Font                               font                          F_Tag          `f_tag_zero()`     }
  { FontSize                           font_size                     F32            24.f               }
  { TabSize                            tab_size                      F32            `24.f*4.f`         }
  
  //- rjf: corner radii
  { CornerRadius00                     corner_radius_00              F32            0                  }
  { CornerRadius01                     corner_radius_01              F32            0                  }
  { CornerRadius10                     corner_radius_10              F32            0                  }
  { CornerRadius11                     corner_radius_11              F32            0                  }
  
  //- rjf: blur size
  { BlurSize                           blur_size                     F32            0                  }
  
  //- rjf: text parameters
  { TextPadding                        text_padding                  F32            2                  }
  { TextAlignment                      text_alignment                UI_TextAlign   UI_TextAlign_Left  }
}

//- rjf: declaring stack node types

@gen
{
  @expand(UI_StackTable a) `typedef struct UI_$(a.name)Node UI_$(a.name)Node; struct UI_$(a.name)Node{UI_$(a.name)Node *next; $(a.type) v;};`
}

//- rjf: declaring all default stack tops

@gen
{
  `#define UI_DeclStackNils \\`;
  `struct\\`;
  `{\\`;
    @expand(UI_StackTable a) `UI_$(a.name)Node $(a.name_lower)_nil_stack_top;\\`;
    `}`;
}

//- rjf: initializing all default stack tops

@gen
{
  `#define UI_InitStackNils(state) \\`;
  @expand(UI_StackTable a) `state->$(a.name_lower)_nil_stack_top.v = $(a.default);\\`;
  ``;
}

//- rjf: declaring all stack nodes & free lists

@gen
{
  `#define UI_DeclStacks \\`;
  `struct\\`;
  `{\\`;
    @expand(UI_StackTable a) `struct { UI_$(a.name)Node *top; $(a.type) bottom_val; UI_$(a.name)Node *free; B32 auto_pop; } $(a.name_lower)_stack;\\`;
    `}`;
}

//- rjf: initing all stack nodes

@gen
{
  `#define UI_InitStacks(state) \\`;
  @expand(UI_StackTable a) `state->$(a.name_lower)_stack.top = &state->$(a.name_lower)_nil_stack_top; state->$(a.name_lower)_stack.bottom_val = $(a.default); state->$(a.name_lower)_stack.free = 0; state->$(a.name_lower)_stack.auto_pop = 0;\\`;
  ``;
}

//- rjf: auto-popping all stacks

@gen
{
  `#define UI_AutoPopStacks(state) \\`
  @expand(UI_StackTable a)
    `if(state->$(a.name_lower)_stack.auto_pop) { ui_pop_$(a.name_lower)(); state->$(a.name_lower)_stack.auto_pop = 0; }\\`;
  ``;
}

//- rjf: decls for the stack function operation headers

@gen
{
  @expand(UI_StackTable a)
    `internal $(a.type) $(=>35) ui_top_$(a.name_lower)(void);`
    @expand(UI_StackTable a)
    `internal $(a.type) $(=>35) ui_bottom_$(a.name_lower)(void);`
    @expand(UI_StackTable a)
    `internal $(a.type) $(=>35) ui_push_$(a.name_lower)($(a.type) v);`
    @expand(UI_StackTable a)
    `internal $(a.type) $(=>35) ui_pop_$(a.name_lower)(void);`
    @expand(UI_StackTable a)
    `internal $(a.type) $(=>35) ui_set_next_$(a.name_lower)($(a.type) v);`
}

//- rjf: defer-loop helpers

@gen @c_file
{
  `#if 0`;
  @expand(UI_StackTable a)
    `#define UI_$(a.name)(v) DeferLoop(ui_push_$(a.name_lower)(v), ui_pop_$(a.name_lower)())`
  `#endif`;
}

//- rjf: decls for the stack operation implementations

@gen @c_file
{
  @expand(UI_StackTable a)
    `internal $(a.type) ui_top_$(a.name_lower)(void) { UI_StackTopImpl(ui_state, $(a.name), $(a.name_lower)) }`;
  @expand(UI_StackTable a)
    `internal $(a.type) ui_bottom_$(a.name_lower)(void) { UI_StackBottomImpl(ui_state, $(a.name), $(a.name_lower)) }`;
  @expand(UI_StackTable a)
    `internal $(a.type) ui_push_$(a.name_lower)($(a.type) v) { UI_StackPushImpl(ui_state, $(a.name), $(a.name_lower), $(a.type), v) }`;
  @expand(UI_StackTable a)
    `internal $(a.type) ui_pop_$(a.name_lower)(void) { UI_StackPopImpl(ui_state, $(a.name), $(a.name_lower)) }`;
  @expand(UI_StackTable a)
    `internal $(a.type) ui_set_next_$(a.name_lower)($(a.type) v) { UI_StackSetNextImpl(ui_state, $(a.name), $(a.name_lower), $(a.type), v) }`;
}
