package path

import "core:strings"
import win32 "core:sys/windows"


SEPARATOR        :: '\\';
SEPARATOR_STRING :: "\\";


@(private)
null_term :: proc "contextless" (str: string) -> string {
	for c, i in str {
		if c == '\x00' {
			return str[:i];
		}
	}
	return str;
}


long :: proc(path: string, allocator := context.temp_allocator) -> string {
	c_path := win32.utf8_to_wstring(path, context.temp_allocator);
	length := win32.GetLongPathNameW(c_path, nil, 0);

	if length == 0 do return "";

	buf := make([]u16, length, context.temp_allocator);

	win32.GetLongPathNameW(c_path, win32.LPCWSTR(&buf[0]), length);

	res := win32.utf16_to_utf8(buf[:length], allocator);

	return null_term(res);
}

short :: proc(path: string, allocator := context.temp_allocator) -> string {
	c_path := win32.utf8_to_wstring(path, context.temp_allocator);
	length := win32.GetShortPathNameW(c_path, nil, 0);

	if length == 0 do return "";

	buf := make([]u16, length, context.temp_allocator);

	win32.GetShortPathNameW(c_path, win32.LPCWSTR(&buf[0]), length);

	res := win32.utf16_to_utf8(buf[:length], allocator);

	return null_term(res);
}

full :: proc(path: string, allocator := context.temp_allocator) -> string {
	c_path := win32.utf8_to_wstring(path, context.temp_allocator);
	length := win32.GetFullPathNameW(c_path, 0, nil, nil);

	if length == 0 do return "";

	buf := make([]u16, length, context.temp_allocator);

	win32.GetFullPathNameW(c_path, length, win32.LPCWSTR(&buf[0]), nil);

	res := win32.utf16_to_utf8(buf[:length], allocator);

	return null_term(res);
}

current :: proc(allocator := context.temp_allocator) -> string {
	length := win32.GetCurrentDirectoryW(0, nil);

	if length == 0 do return "";

	buf := make([]u16, length, context.temp_allocator);

	win32.GetCurrentDirectoryW(length, win32.LPCWSTR(&buf[0]));

	res := win32.utf16_to_utf8(buf[:length], allocator);

	return strings.trim_null(res);
}


exists :: proc(path: string) -> bool {
	c_path  := win32.utf8_to_wstring(path, context.temp_allocator);
	attribs := win32.GetFileAttributesW(c_path);

	return i32(attribs) != win32.INVALID_FILE_ATTRIBUTES;
}

is_dir :: proc(path: string) -> bool {
	c_path  := win32.utf8_to_wstring(path, context.temp_allocator);
	attribs := win32.GetFileAttributesW(c_path);

	return (i32(attribs) != win32.INVALID_FILE_ATTRIBUTES) && (attribs & win32.FILE_ATTRIBUTE_DIRECTORY == win32.FILE_ATTRIBUTE_DIRECTORY);
}

is_file :: proc(path: string) -> bool {
	c_path  := win32.utf8_to_wstring(path, context.temp_allocator);
	attribs := win32.GetFileAttributesW(c_path);

	return (i32(attribs) != win32.INVALID_FILE_ATTRIBUTES) && (attribs & win32.FILE_ATTRIBUTE_DIRECTORY != win32.FILE_ATTRIBUTE_DIRECTORY);
}


drive :: proc(path: string, new := false, allocator := context.allocator) -> string {
	if len(path) >= 3 {
		letter := path[:2];

		if path[1] == ':' && (path[2] == '\\' || path[2] == '/') {
			return new ? strings.clone(path[:2], allocator) : path[:2];
		}
	}

	return "";
}
