#pragma once
// #TODO: #strings:
  // [ ] see: #Parsing stuff:
  // [?] How do I accept variadic arguments of any type to my print function?
  // [ ] Need to sort out how formatted strings and string builders are allocated
  // [ ] Separate functions for temp alloc (tprint??)
  // [ ] I should also put path manipulation here or in a separate file?

struct string {
  s64 count;
  u8* data;
  // Construct from a string literal or C-string
  string () { // default constructor
    count = 0;
    data = nullptr;
  }
  
  string (char* cstr) {
    count = strlen(cstr);
    data = (u8*)cstr;
  }
  
  string (s64 _count, char* str) { count = _count; data = (u8*)str; }
  string (s64 _count, u8* str) { count = _count; data = str; }
  
  bool operator==(const string& other) const {
    string first_string = *this;
    string second_string = other;
    // return strings_match(*this, other);
    if (first_string.count != second_string.count) {
      return false;
    }
  
    for (s64 i = 0; i < first_string.count; i += 1) {
      if (first_string.data[i] != second_string.data[i]) {
        return false;
      }
    }
    
    return true;
  }
  
  bool operator ! () {
    Assert(count >= 0);
    return (data == nullptr || count == 0);
  }
};

struct wstring {
  s64 count;
  u16* data;
  
  wstring () { // default constructor
    count = 0;
    data = nullptr;
  }
  
  wstring (s32 length) {
    data = NewArray<u16>(length + 1);
    s32 length_bytes = (length + 1) * sizeof(u16);
    count = length_bytes;
  }
  
  wstring (s64 _count, u16* _data) {
    count = _count;
    data = _data;
  }
  
  bool operator ! () {
    Assert(count >= 0);
    return (data == nullptr || count == 0);
  }
};

// ~Keep these API
bool is_valid (string s);
bool is_c_string (string s);
u8*  to_c_string (string s);         // #allocates
string copy_string (string s);       // #allocates, returned string is #null-terminated.
string copy_string_no_context (string s);
string copy_string (char* c_string); // #allocates, returned string is #null-terminated.
string to_string (ArrayView<u8> str);
ArrayView<u8> to_view (string s);
void free(string& s);

// String manipulation & comparison
force_inline string string_view (string s, s64 start_index, s64 view_count);
bool strings_match (string first_string, string second_string);

// #Unicode 
string wide_to_utf8 (u16* source, s32 length=-1);
wstring utf8_to_wide (string source);

string format_string_temp (char* format, ...);
string format_string (char* format, ...);
string format_string_no_context (char* format, ...);

string to_lower_copy (string s_orig);

string DEFAULT_SPACES = "\r\t\n";
string trim_right (string s, string chars=DEFAULT_SPACES, bool replace_with_zeros=true);

// #TODO #Parsing stuff:
// is_white_space(char: u8)
// advance
// eat_spaces

// string to type or type to string conversions
// s64 string_to_int (string v, s32 base = 10, s64* remainder=nullptr);
// f64 string_to_f64
// f32 string_to_f32

// Need an API for inserting various types (ints, floats, etc.) into a String_Builder, and advancing 
// the count. 

