/*
 * DWN - Desktop Window Manager
 * Abstract String Type
 */

#ifndef WM_STRING_H
#define WM_STRING_H

#include "wm_types.h"

#include <stdarg.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

/*==============================================================================
 * String Lifecycle
 *============================================================================*/

WmString* wm_string_new(const char *str);
WmString* wm_string_new_empty(void);
WmString* wm_string_new_sized(size_t capacity);
WmString* wm_string_new_printf(const char *fmt, ...);
WmString* wm_string_new_vprintf(const char *fmt, va_list args);
WmString* wm_string_new_n(const char *str, size_t n);

void wm_string_destroy(WmString *str);
WmString* wm_string_clone(const WmString *str);

/*==============================================================================
 * String Operations
 *============================================================================*/

void wm_string_append(WmString *str, const char *suffix);
void wm_string_append_char(WmString *str, char c);
void wm_string_append_n(WmString *str, const char *suffix, size_t n);
void wm_string_append_printf(WmString *str, const char *fmt, ...);
void wm_string_append_vprintf(WmString *str, const char *fmt, va_list args);
void wm_string_append_string(WmString *str, const WmString *suffix);

void wm_string_prepend(WmString *str, const char *prefix);
void wm_string_prepend_char(WmString *str, char c);

void wm_string_insert(WmString *str, size_t pos, const char *insert);
void wm_string_insert_char(WmString *str, size_t pos, char c);
void wm_string_insert_string(WmString *str, size_t pos, const WmString *insert);

void wm_string_erase(WmString *str, size_t pos, size_t len);
void wm_string_clear(WmString *str);

/*==============================================================================
 * String Queries
 *============================================================================*/

const char* wm_string_cstr(const WmString *str);
char* wm_string_detach(WmString *str);

size_t wm_string_length(const WmString *str);
size_t wm_string_capacity(const WmString *str);
size_t wm_string_bytes(const WmString *str);

bool wm_string_is_empty(const WmString *str);
bool wm_string_is_null(const WmString *str);

char wm_string_char_at(const WmString *str, size_t pos);

/*==============================================================================
 * String Comparison
 *============================================================================*/

bool wm_string_equals(const WmString *str1, const WmString *str2);
bool wm_string_equals_cstr(const WmString *str, const char *cstr);

int wm_string_compare(const WmString *str1, const WmString *str2);
int wm_string_compare_cstr(const WmString *str, const char *cstr);
int wm_string_case_compare(const WmString *str1, const WmString *str2);
int wm_string_case_compare_cstr(const WmString *str, const char *cstr);

/*==============================================================================
 * String Searching
 *============================================================================*/

bool wm_string_contains(const WmString *str, const char *needle);
bool wm_string_contains_char(const WmString *str, char c);

size_t wm_string_find(const WmString *str, const char *needle, size_t start);
size_t wm_string_find_char(const WmString *str, char c, size_t start);
size_t wm_string_find_last(const WmString *str, const char *needle);
size_t wm_string_find_last_char(const WmString *str, char c);

bool wm_string_starts_with(const WmString *str, const char *prefix);
bool wm_string_starts_with_char(const WmString *str, char c);
bool wm_string_ends_with(const WmString *str, const char *suffix);
bool wm_string_ends_with_char(const WmString *str, char c);

/*==============================================================================
 * String Modification
 *============================================================================*/

void wm_string_trim(WmString *str);
void wm_string_trim_left(WmString *str);
void wm_string_trim_right(WmString *str);

void wm_string_replace(WmString *str, const char *search, const char *replace);
void wm_string_replace_char(WmString *str, char search, char replace);
size_t wm_string_replace_all(WmString *str, const char *search, const char *replace);

void wm_string_to_lower(WmString *str);
void wm_string_to_upper(WmString *str);

void wm_string_reverse(WmString *str);

/*==============================================================================
 * String Substrings
 *============================================================================*/

WmString* wm_string_substring(const WmString *str, size_t start, size_t len);
WmString* wm_string_left(const WmString *str, size_t n);
WmString* wm_string_right(const WmString *str, size_t n);

/*==============================================================================
 * String Splitting and Joining
 *============================================================================*/

WmContainer* wm_string_split(const WmString *str, const char *delimiter);
WmContainer* wm_string_split_chars(const WmString *str, const char *delimiters);
WmContainer* wm_string_split_lines(const WmString *str);

WmString* wm_string_join(const WmContainer *strings, const char *separator);
WmString* wm_string_join_cstr(const char **strings, size_t count, const char *separator);

/*==============================================================================
 * String Formatting
 *============================================================================*/

void wm_string_printf(WmString *str, const char *fmt, ...);
void wm_string_vprintf(WmString *str, const char *fmt, va_list args);

/*==============================================================================
 * String Validation
 *============================================================================*/

bool wm_string_is_valid_utf8(const WmString *str);
bool wm_string_is_ascii(const WmString *str);
bool wm_string_is_numeric(const WmString *str);
bool wm_string_is_integer(const WmString *str);
bool wm_string_is_float(const WmString *str);

/*==============================================================================
 * String Conversion
 *============================================================================*/

int wm_string_to_int(const WmString *str, int default_val);
long wm_string_to_long(const WmString *str, long default_val);
float wm_string_to_float(const WmString *str, float default_val);
double wm_string_to_double(const WmString *str, double default_val);
bool wm_string_to_bool(const WmString *str, bool default_val);

WmString* wm_string_from_int(int val);
WmString* wm_string_from_long(long val);
WmString* wm_string_from_float(float val, int precision);
WmString* wm_string_from_double(double val, int precision);
WmString* wm_string_from_bool(bool val);

/*==============================================================================
 * String Hash
 *============================================================================*/

uint32_t wm_string_hash(const WmString *str);
uint32_t wm_string_hash_cstr(const char *str);

/*==============================================================================
 * String Escaping
 *============================================================================*/

WmString* wm_string_escape_json(const WmString *str);
WmString* wm_string_escape_xml(const WmString *str);
WmString* wm_string_escape_html(const WmString *str);
WmString* wm_string_escape_shell(const WmString *str);
WmString* wm_string_escape_regex(const WmString *str);

WmString* wm_string_unescape_json(const WmString *str);
WmString* wm_string_unescape_xml(const WmString *str);
WmString* wm_string_unescape_html(const WmString *str);

/*==============================================================================
 * Static String Helpers
 *============================================================================*/

static inline bool wm_cstr_is_empty(const char *str) {
    return str == NULL || str[0] == '\0';
}

static inline size_t wm_cstr_length(const char *str) {
    return str == NULL ? 0 : strlen(str);
}

static inline bool wm_cstr_equals(const char *a, const char *b) {
    if (a == b) return true;
    if (a == NULL || b == NULL) return false;
    return strcmp(a, b) == 0;
}

static inline bool wm_cstr_case_equals(const char *a, const char *b) {
    if (a == b) return true;
    if (a == NULL || b == NULL) return false;
    return strcasecmp(a, b) == 0;
}

static inline void wm_cstr_copy(char *dest, const char *src, size_t size) {
    if (size == 0) return;
    strncpy(dest, src, size - 1);
    dest[size - 1] = '\0';
}

#ifdef __cplusplus
}
#endif

#endif /* WM_STRING_H */
