// File: miklhh[P]tetris/src/input.cpp
// Function: keyboard_key_timer(SDL_Scancode, unsigned char const*)
static bool keyboard_key_timer(SDL_Scancode scancode, keyboard_state_t* keyboard_state)
{
    using namespace std::chrono;

    static SDL_Scancode     last_scancode;
    static bool             first_time_key_repeat   = false;
    static bool             last_scancode_released  = false;
    static auto		        last_call_timestamp     = high_resolution_clock::now();
    auto                    this_call_timestamp     = high_resolution_clock::now();
    milliseconds            time_since_last_call    = duration_cast<milliseconds>(this_call_timestamp - last_call_timestamp);


    /* Test if 'this' key (scancode) is pressed, otherwise always return false. */
    if (keyboard_state[scancode])
    {
        /* Test if another key has been pressed since last time. */
        if (last_scancode != scancode)
        {
            last_scancode           = scancode;
            first_time_key_repeat   = true;
            last_scancode_released  = false;
            last_call_timestamp     = this_call_timestamp;
            return true;
        }

        /* Else, the key is pressed, and the key is the same as the last key pressed. */
        else
        {
            /* Two cases. If this is the first time the keycode is repeated we wait 
             * FIRST_REPEAT_WAIT_TIME milliseconds before giving key allowance. */
            if (first_time_key_repeat)
            {
                /* If the key has been released since last call, return true. */
                if (last_scancode_released)
                {
                    last_scancode_released  = false;
                    last_call_timestamp     = this_call_timestamp;
                    return true;
                }


                if (time_since_last_call.count() < FIRST_REPEAT_WAIT_TIME)
                    return false;
                else
                {
                    first_time_key_repeat   = false;
                    last_call_timestamp     = this_call_timestamp;
                    return true;
                }
            }

            /* Else if this isn't the first time the keycode is repeated we wait
             * REPEAT_WAIT_TIME milliseconds before giving key allowance. */
            else
            {
                if (time_since_last_call.count() < REPEAT_WAIT_TIME)
                    return false;
                else
                {
                    last_call_timestamp = this_call_timestamp;
                    return true;
                }
            }
        }
    }

    /* Else, if the key is not pressed. */
    else
    {
        if (last_scancode == scancode)
        {
            last_scancode_released  = true;
            first_time_key_repeat   = true;
        }
        return false;
    }   
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpb $0x0, 0x4b2a(%rip)      # 0x8b10
jne 0x4011
leaq 0x4b21(%rip), %rdi      # 0x8b10
callq 0x2230
cmpl $0x0, %eax
je 0x4011
callq 0x2060
movq %rax, 0x4b03(%rip)      # 0x8b08
leaq 0x4b04(%rip), %rdi      # 0x8b10
callq 0x2110
callq 0x2060
movq %rax, -0x18(%rbp)
leaq -0x18(%rbp), %rdi
leaq 0x4ae3(%rip), %rsi      # 0x8b08
callq 0x3c30
movq %rax, -0x28(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x3c00
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movl -0x8(%rbp), %ecx
cmpb $0x0, (%rax,%rcx)
je 0x4101
movl 0x4aaa(%rip), %eax      # 0x8afc
cmpl -0x8(%rbp), %eax
je 0x4082
movl -0x8(%rbp), %eax
movl %eax, 0x4a9c(%rip)      # 0x8afc
movb $0x1, 0x4a99(%rip)      # 0x8b00
movb $0x0, 0x4a93(%rip)      # 0x8b01
movq -0x18(%rbp), %rax
movq %rax, 0x4a8f(%rip)      # 0x8b08
movb $0x1, -0x1(%rbp)
jmp 0x411e
testb $0x1, 0x4a77(%rip)      # 0x8b00
je 0x40db
testb $0x1, 0x4a6f(%rip)      # 0x8b01
je 0x40ac
movb $0x0, 0x4a66(%rip)      # 0x8b01
movq -0x18(%rbp), %rax
movq %rax, 0x4a62(%rip)      # 0x8b08
movb $0x1, -0x1(%rbp)
jmp 0x411e
leaq -0x20(%rbp), %rdi
callq 0x3c80
cmpq $0x96, %rax
jge 0x40c3
movb $0x0, -0x1(%rbp)
jmp 0x411e
movb $0x0, 0x4a36(%rip)      # 0x8b00
movq -0x18(%rbp), %rax
movq %rax, 0x4a33(%rip)      # 0x8b08
movb $0x1, -0x1(%rbp)
jmp 0x411e
leaq -0x20(%rbp), %rdi
callq 0x3c80
cmpq $0x32, %rax
jge 0x40f0
movb $0x0, -0x1(%rbp)
jmp 0x411e
movq -0x18(%rbp), %rax
movq %rax, 0x4a0d(%rip)      # 0x8b08
movb $0x1, -0x1(%rbp)
jmp 0x411e
movl 0x49f5(%rip), %eax      # 0x8afc
cmpl -0x8(%rbp), %eax
jne 0x411a
movb $0x1, 0x49ee(%rip)      # 0x8b01
movb $0x1, 0x49e6(%rip)      # 0x8b00
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax)