#include "str.h"
#include "aliases.h"
#include "mem_arena.h"
#include <stddef.h>
#include <string.h>

#define CAPACITY_SCALAR 8

internal Arena *get_temp_arena(void);
internal void destroy_temp_arena(Arena *arena);

Str8 str8(Arena *arena, char *str) {
  if (!str) {
    return (Str8){0};
  }

  u64 length = strlen(str);
  Str8 output = {
      .str = str,
      .length = length,
      .capacity = length,
  };

  if (arena) {
    output.capacity *= CAPACITY_SCALAR;

    output.str = wapp_mem_arena_alloc(arena, output.capacity);
    if (!output.str) {
      return (Str8){0};
    }

    strncpy(output.str, str, output.length);
  }

  return output;
}

Str8 str8_copy(Arena *arena, const Str8 *str) {
  if (!arena) {
    return str8_lit(str->str);
  }

  char *tmp = wapp_mem_arena_alloc(arena, str->capacity);
  if (!tmp) {
    return str8_lit(str->str);
  }

  strncpy(tmp, str->str, str->length);

  return (Str8){
      .str = tmp,
      .length = str->length,
      .capacity = str->capacity,
  };
}

i32 str8_concat(Arena *arena, Str8 *dst, char *src) {
  if (!src || !dst) {
    return STR_OP_FAILED;
  }

  u64 src_length = strlen(src);
  if (src_length + dst->length > dst->capacity) {
    if (!arena) {
      return STR_OP_FAILED;
    }

    u64 capacity = dst->capacity * CAPACITY_SCALAR + src_length;
    char *str = wapp_mem_arena_alloc(arena, capacity);
    if (!str) {
      return STR_OP_FAILED;
    }

    strncpy(str, dst->str, dst->length);
    strncpy(str + dst->length, src, src_length);

    dst->str = str;
    dst->length = dst->length + src_length;
    dst->capacity = capacity;

    return STR_OP_SUCEEDED;
  }

  strncpy(dst->str + dst->length, src, src_length);
  return STR_OP_SUCEEDED;
}

Str8 str8_substr(Arena *arena, const Str8 *str, u64 start, u64 count) {
  if (start > str->length || start + count > str->length) {
    return (Str8){0};
  }

  Str8 tmp = {
      .str = str->str + start,
      .length = count,
      .capacity = count,
  };

  return str8_copy(arena, &tmp);
}
