format ELF64 executable 3
include "lib/linux_syscall.inc"
include "lib/itoa.inc"

segment readable executable
entry main

main:
	;; Determine the file size of the input file
	stat input_filename, file_stat

	;; Open a file descriptor for the input file
	open input_filename, 0
	mov [input_fd], rax

        ;; Map the input file into memory
	mmap 0, [file_stat.st_size], PROT_READ, MAP_PRIVATE, [input_fd], 0
	mov [input], rax

	;; Close the input file
	close [input_fd]

	;; Setup the loop variables for counting 
	;; rbx starts at the first byte of input, and is incremented to read it all
	mov rbx, [input]
	;; rcx tracks the current floor
	mov rcx, 0
	;; rdx counts down from the file's size to 0
	mov rdx, [file_stat.st_size]

lp:
	;; Is the current character the "go up" character?
	cmp byte [rbx], '('
	;; If so, jump to "up"
	je up
	;; Is the current character the "go down" character?
	cmp byte [rbx], ')'
	;; If so, it's the "go down" character, so decrement the current floor
	je down
	;; Otherwise it's the EOF probably, skip it
	jmp other
up:
	;; We should "go up", so increment the current floor
	inc rcx
	jmp other
down:
	;; We should "go down", so decrement the current floor
	dec rcx
other:
	;; Check the next character in the file
	inc rbx
	;; Count down the file's length
	dec rdx
	;; If we haven't reached the end of the file, loop
	jnz lp

	;; Put part 1's answer in rax
	mov rax, rcx
	mov rbx, part_1
	call itoa

	;; Write part 1's verbiage to STDOUT
	write STDOUT, part_1_verbiage, 8
	write STDOUT, part_1, 6
	write STDOUT, newline, 1

	;; Setup the loop variables for counting 
	;; rbx starts at the first byte of input, and is incremented to read it all
	mov rbx, [input]
	;; rcx tracks the current floor
	mov rcx, 0
	;; rdx tracks how many steps we've made so far
	mov rdx, 0
lp2:
	cmp byte [rbx], '('
	je up2
	dec rcx
	jmp moved2
up2:
	inc rcx
moved2:
	inc rdx
	cmp rcx, 0
	jl done
	inc rbx
	jnz lp2
done:

	;; Put part 2's answer in rax
	mov rax, rdx
	mov rbx, part_2
	call itoa

	;; Write part 2's verbiage to STDOUT
	write STDOUT, part_2_verbiage, 8
	write STDOUT, part_2, 6
	write STDOUT, newline, 1

	;; Unmap the mapped file
	munmap [input], [file_stat.st_size]

	;; Done!
	exit 0

segment readable writable
input_filename db '../data/2015/1/input.txt', 0
input_fd dq -1
input dq -1
part_1_verbiage db 'Part 1: ', 0
part_1 db '     ', 0
part_2_verbiage db 'Part 2: ', 0
part_2 db '     ', 0
newline db 10
file_stat s_stat