fn print(msg: string) #[builtin(Print)] {}
fn println(msg: string) { print(msg + "\n") }

fn int_to_string(number: int) -> string #[builtin(IntToString)] {}

fn string_push_char(str: string, value: int) -> string #[builtin(StringPushChar)] {}
fn string_char_at(str: string, index: int) -> int #[builtin(StringCharAt)] {}
fn string_length(str: string) -> int #[builtin(StringLength)] {}
fn string_to_int(str: string) -> int #[builtin(StringToInt)] {}

fn string_array_new() -> [string] #[builtin(ArrayNew)] {}
fn string_array_push(array: [string], value: string) #[builtin(ArrayPush)] {}
fn string_array_length(array: [string]) -> int #[builtin(ArrayLength)] {}
fn string_array_at(array: [string], index: int) -> string #[builtin(ArrayAt)] {}

fn int_array_new() -> [int] #[builtin(ArrayNew)] {}
fn int_array_push(array: [int], value: int) #[builtin(ArrayPush)] {}
fn int_array_length(array: [int]) -> int #[builtin(ArrayLength)] {}
fn int_array_at(array: [int], index: int) -> int #[builtin(ArrayAt)] {}

fn file_open(filename: string, mode: string) -> int #[builtin(FileOpen)] {}
fn file_close(file: int) #[builtin(FileClose)] {}
fn file_write_string(file: int, content: string) -> int #[builtin(FileWriteString)] {}
fn file_read_char(file: int) -> int #[builtin(FileReadChar)] {}
fn file_read_to_string(file: int) -> string #[builtin(FileReadToString)] {}
fn file_flush(file: int) #[builtin(FileFlush)] {}
fn file_eof(file: int) -> bool #[builtin(FileEof)] {}


fn stdin() -> int { 0 }
fn stdout() -> int { 1 }
fn stderr() -> int { 2 }

fn file_read_line(file: int) -> string {
    let line = "";
    loop {
        if file_eof(file) {
            break;
        }
        let ch = file_read_char(file);
        if ch == "\n"[0] {
            break;
        }
        line = string_push_char(line, ch);
    }
    line
}

fn read_text_file(filename: string) -> string {
    let file = file_open(filename, "r");
    let text = file_read_to_string(file);
    file_close(file);
    text
}

fn input(prompt: string) -> string {
    print("> ");
    file_flush(stdout());
    file_read_line(stdin())
}

fn char(ch: string) -> int {
    ch[0]
}

fn abs(number: int) -> int {
    let result = number;
    if number < 0 {
        result = number - (number * 2);
    }
    result
}

fn split(str: string, seperator: int) -> [string] {
    let result: [string] = string_array_new();

    let i = 0;
    let current_str = "";
    loop {
        if i >= string_length(str) {
            break;
        }
        let char = str[i];
        if char == seperator {
            string_array_push(result, current_str);
            current_str = "";
        } else {
            current_str = string_push_char(current_str, char);
        }
        i = i + 1;
    }
    string_array_push(result, current_str);
    result
}

fn slice(str: string, from: int, to: int) -> string {
    let result = "";
    let i = from;
    loop {
        if i >= string_length(str) {
            break;
        }
        if i >= to {
            break;
        }
        result = string_push_char(result, str[i]);
        i = i + 1;
    }
    result
}

fn array_clone(array: [int]) -> [int] {
    let len = int_array_length(array);
    let result = int_array_new();
    let i = 0;
    loop {
        if i >= len { break; }
        int_array_push(result, array[i]);
        i = 1 + 1;
    }
    result
}

fn array_sort_mut(array: [int]) {
    let len = int_array_length(array);
    for (let i = 0; i < len - 1; i += 1) {
        let min_i = i;
        let min_val = array[i];
        for (let j = i + 1; j < len; j += 1) {
            if array[j] < min_val {
                min_i = j;
                min_val = array[j];
            }
        }

        let tmp = array[i];
        array[i] = array[min_i];
        array[min_i] = tmp;
    }
}

fn array_sort_mut_triangle(array: [int]) {
    let len = int_array_length(array);
    for (let i = 0; i < len; i += 1) {
        for (let j = i + 1; j < len; j += 1) {
            if array[j] < array[i] {
                let tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
            }
        }
    }
}

fn array_to_sorted(array: [int]) -> [int] {
    let cloned = array_clone(array);
    array_sort_mut(array);
    cloned
}

fn main() {
    let location_ids = read_text_file("examples/advent_of_code/day1.txt");
    let location_ids_split = split(location_ids, char("\n"));
    let i = 0;
    let left_ids: [int] = int_array_new();
    let right_ids: [int] = int_array_new(); 
    let location_len = string_array_length(location_ids_split);
    for (let i = 0; i < location_len; i += 1) {
        int_array_push(left_ids, string_to_int(slice(location_ids_split[i], 0, 5)));
        int_array_push(right_ids, string_to_int(slice(location_ids_split[i], 8, 13)));
    }
    array_sort_mut(left_ids);
    array_sort_mut(right_ids);
    let sum = 0;
    let left_ids_len = int_array_length(left_ids);
    for (let i = 0; i < left_ids_len; i += 1) {
        let difference = abs(left_ids[i] - right_ids[i]);
        sum += difference;
    }
    println(int_to_string(sum));
}
