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

#define INITIAL_BUFFER_SIZE 2

char *input_buffer;

char *aoc_read_input(void) {
  int buffer_size = INITIAL_BUFFER_SIZE;
  input_buffer = malloc(buffer_size);
  int chars_read = read(STDIN_FILENO, input_buffer, buffer_size);
  char *buffer_position = &input_buffer[chars_read];

  while (chars_read == buffer_size) {
    buffer_size *= 2;
    input_buffer = realloc(input_buffer, buffer_size);
    buffer_position = &input_buffer[chars_read];
    chars_read += read(STDIN_FILENO, buffer_position, buffer_size / 2);
  }

  input_buffer[chars_read] = 0;
  return input_buffer;
}

char *read_line_buffer = NULL;
char *seek = NULL;

char *aoc_read_line(void) {
  if (input_buffer == NULL) aoc_read_input();
  if (read_line_buffer == NULL) {
    read_line_buffer = malloc(strlen(input_buffer) + 1);
    strcpy(read_line_buffer, input_buffer);
  }

  if (seek == NULL) seek = read_line_buffer;

  char *line_break = strstr(seek, "\n");
  if (line_break == NULL) return NULL;

  *line_break = '\0';
  char *token = seek;
  seek = line_break + 1;
  return token;
}

void aoc_reset_read_line(void) {
  strcpy(read_line_buffer, input_buffer);
  seek = NULL;
}

void aoc_free(void) {
  free(input_buffer);
  free(read_line_buffer);
}

int aoc_line_count(void) {
  if (input_buffer == NULL) aoc_read_input();

  int count = 0;
  for (int i = 0; i < strlen(input_buffer); i++) {
    if (input_buffer[i] == '\n') count++;
  }
  return count;
}

int aoc_sort_int(const void *a, const void *b) {
  return *(int*) a - *(int*) b;
}