// Written by retoor@molodetz.nl

// This header file contains utility functions for manipulating file system
// paths, focusing primarily on expanding paths starting with '~' to the home
// directory.

// This code uses standard libraries: stdio.h, stdlib.h, and string.h, and
// conditionally includes the posix libraries pwd.h and unistd.h when expanding
// the home directory manually.

// MIT License
//
// Permission is granted to use, copy, modify, merge, distribute, sublicense,
// and/or sell copies of the Software. The license includes conditions about
// providing a copy of the license and the limitation of liability and warranty.

#ifndef UTILS_H
#define UTILS_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef _WIN32
#include <windows.h>
#else
#include <limits.h>
#include <pwd.h>
#include <unistd.h>
#endif

void get_current_directory() {
  char buffer[PATH_MAX];

#ifdef _WIN32
  DWORD length = GetCurrentDirectory(PATH_MAX, buffer);
  if (length > 0 && length < PATH_MAX) {
    printf("Current Directory: %s\n", buffer);
  } else {
    printf("Error getting current directory.\n");
  }
#else
  if (getcwd(buffer, sizeof(buffer)) != NULL) {
    printf("Current Directory: %s\n", buffer);
  } else {
    perror("Error getting current directory");
  }
#endif
}

char *expand_home_directory(const char *path) {
  if (path[0] != '~') {
    return strdup(path); // Return the original path if it doesn't start with ~
  }

  char *home_dir;

#ifdef _WIN32
  home_dir = getenv("USERPROFILE"); // Get home directory on Windows
#else
  struct passwd *pw = getpwuid(getuid());
  home_dir = pw->pw_dir; // Get home directory on Linux
#endif

  if (home_dir == NULL) {
    return NULL; // Error getting home directory
  }

  // Allocate memory for the expanded path
  size_t expanded_size = strlen(home_dir) + strlen(path);
  char *expanded_path = (char *)malloc(expanded_size);
  if (expanded_path == NULL) {
    return NULL; // Memory allocation error
  }

  // Construct the expanded path
  snprintf(expanded_path, expanded_size, "%s%s", home_dir, path + 1);
  return expanded_path;
}

unsigned long hash(const char *str) {
  unsigned long hash = 5381; // Starting value
  int c;

  while ((c = *str++)) {
    hash = ((hash << 5) + hash) + c; // hash * 33 + c
  }

  return hash;
}

char *joinpath(const char *base_url, const char *path) {
  static char result[1024];
  result[0] = '\0';
  strcat(result, base_url);
  if (base_url[strlen(base_url) - 1] != '/') {
    strcat(result, "/");
  }
  if (path[0] == '/') {
    path++;
  }
  strcat(result, path);
  return result;
}

char *read_file(const char *path) {
  char *expanded_path = expand_home_directory(path);
  FILE *file = fopen(expanded_path, "r");
  free(expanded_path);
  if (file == NULL) {
    return NULL;
  }
  fseek(file, 0, SEEK_END);
  long size = ftell(file);
  fseek(file, 0, SEEK_SET);

  char *buffer = (char *)malloc(size + 1);
  size_t read = fread(buffer, 1, size, file);
  if (read == 0) {
    free(buffer);
    return NULL;
  }

  fclose(file);
  buffer[read] = '\0';
  return buffer;
}
#endif