#ifndef MR4TH_CMDLN_H
#define MR4TH_CMDLN_H

////////////////////////////////
// Types: Command Line Parsing

typedef struct CMDLN_Params{
  String8 raw;
  String8List list;
} CMDLN_Params;

typedef struct CMDLN_Node{
  struct CMDLN_Node *next;
  String8 string;
  CMDLN_Params *params;
  // (params ==  0 ) -> 'input' (not a flag)
  // (params !=  0 ) -> flag
  // (params == nil) -> flag has no parameters
} CMDLN_Node;

typedef CMDLN_Node CMDLN_Flag;

typedef struct CMDLN{
  String8List raw;
  String8 program;
  CMDLN_Node *first;
  CMDLN_Node *last;
  U64 input_count;
  U64 flag_count;
  CMDLN_Node **inputs;
  CMDLN_Node **flags;
} CMDLN;

////////////////////////////////
// Functions: Command Line Parsing

MR4TH_SYMBOL CMDLN*        cmdln_from_args(Arena *arena, String8List *args);
MR4TH_SYMBOL CMDLN_Params* cmdln_params_from_string(Arena *arena, String8 flag_param);

MR4TH_SYMBOL U64           cmdln_input_count(CMDLN *cmdln);
MR4TH_SYMBOL String8       cmdln_input_from_idx(CMDLN *cmdln, U64 idx);

MR4TH_SYMBOL U64           cmdln_flag_count(CMDLN *cmdln);
MR4TH_SYMBOL CMDLN_Flag*   cmdln_flag_from_idx(CMDLN *cmdln, U64 idx);

MR4TH_SYMBOL CMDLN_Params* cmdln_get_params(CMDLN *cmdln, String8 flagstr, char abbrev);
MR4TH_SYMBOL B32           cmdln_has_flag(CMDLN *cmdln, String8 flagstr, char abbrev);
MR4TH_SYMBOL String8       cmdln_get_str8(CMDLN *cmdln, String8 flagstr, char abbrev);
MR4TH_SYMBOL S64           cmdln_get_s64(CMDLN *cmdln, String8 flagstr, char abbrev);
MR4TH_SYMBOL F64           cmdln_get_f64(CMDLN *cmdln, String8 flagstr, char abbrev);

MR4TH_SYMBOL S64           cmdln_s64_from_str8(String8 valstr);
MR4TH_SYMBOL F64           cmdln_f64_from_str8(String8 valstr);

MR4TH_SYMBOL void cmdln_dump(Arena *arena, String8List *out, CMDLN *cmdln, U32 indent);

/* TODO:
** [ ] fuzz
** [ ] built in parser diagnostics
** [ ] built in misuse feedback
** [ ] help structurer
*/

#endif //MR4TH_CMDLN_H
