; Returns:
; rax - 0
; Errors (in rax):
; rax - 0 - EOF
; rax - -1024 - line too long
; rax - other negative - from read(2)
; Arguments:
; rdi - fd
; rsi - address of client within clients array
; rdx - pollfds index
; Variables:
; rbx - pollfds index
; r12 - client buffer
; r13 - start of line scanning
; r14 - client buffer end
client__pollin:
    push rbx
    push r12
    push r13
    push r14

    mov rbx, rdx
    mov r12, rsi
    add r12, OFFSET_CLIENT_BUFFER
    mov r13, 0
    mov r13b, [rsi + OFFSET_CLIENT_BUFFER_LEN]
    add r13, r12
    mov r14, r12
    add r14, 255

    mov rax, SYS_READ
    mov rsi, r13
    mov rdx, 255
    sub dl, [rsi + OFFSET_CLIENT_BUFFER_LEN]
    syscall

    cmp rax, 0
    jle client__pollin__return  ; TODO verify this shit

    ; buffer_len += read(2) length
    add [r12 - OFFSET_CLIENT_BUFFER + OFFSET_CLIENT_BUFFER_LEN], al

    mov rdi, r13
    mov rsi, rax
    call scanline

    cmp rax, 0
    je client__pollin__no_line

    mov rax, 1
    mov word [pollfds + rbx * pollfd_size + 4], POLLOUT

client__pollin__return:
    pop r14
    pop r13
    pop r12
    pop rbx
    ret

client__pollin__no_line:
    mov r10, r13
    add r10, rax
    cmp r10, r14
    jge client__pollin__line_too_long
    mov rax, 1
    jmp client__pollin__return

client__pollin__line_too_long:
    mov rax, -1024
    jmp client__pollin__return


; Returns:
; rax - non-negative from write(2)
; Errors:
; rax - -1024 - no line was buffered
; rax - other negative - from write(2)
; Arguments:
; rdi - fd
; rsi - address of client within clients array
; rdx - pollfds index
; Variables:
; rbx - pollfds index
; r12 - address of client within clients array
; r13 - line length
; r11 - client buffer end of text after call to write(2)
client__pollout:
    push rbx
    push r12
    push r13

    mov rbx, rdx
    mov r12, rsi

    push rdi
    mov rdi, r12
    add rdi, OFFSET_CLIENT_BUFFER
    mov rsi, 255
    call scanline
    pop rdi

    ; poll(2)'d for POLLOUT but we had no line buffered;
    ; should be impossible
    cmp rax, 0
    je client__pollout__no_line

    mov r13, rax

    mov rax, SYS_WRITE
    mov rsi, r12
    add rsi, OFFSET_CLIENT_BUFFER
    mov rdx, r13
    syscall

    ; error from write(2)
    cmp rax, 0
    jl client__pollout__return

    mov r10, r12
    mov r11, 0
    mov r11b, [r12 + OFFSET_CLIENT_BUFFER_LEN]
    add r11, r12
    sub r11, rax

client__pollout__shunt:
    cmp r10, r11
    jge client__pollout__shunt__finished
    mov r8b, [r10 + rax]
    mov [r10], r8b
    add r10, 1
    jmp client__pollout__shunt

client__pollout__shunt__finished:
    ; buffer_len -= rax
    sub [r12 + OFFSET_CLIENT_BUFFER_LEN], al
    cmp rax, r13
    jl client__pollout__return
    mov word [pollfds + rbx * pollfd_size + 4], POLLIN

client__pollout__return:
    pop r13
    pop r12
    pop rbx
    ret

client__pollout__no_line:
    mov rax, -1024
    jmp client__pollout__return

; rdi - fd
client__shutdown_close:
    mov rax, SYS_SHUTDOWN
    push rdi
    mov rsi, SHUT_RDWR
    syscall

    mov rax, SYS_CLOSE
    pop rdi
    syscall

    ret