// File: therealgymmy[P]HelicopterGame/src/events.cpp
// Function: pollForEvents(EventsArg*)
void pollForEvents (EventsArg *eventsArg) {
    Resources       *resources = eventsArg->resources_;
    XHandler        *xhandler  = eventsArg->xhandler_;
    pthread_mutex_t *mutex     = eventsArg->mutex_;

    Display *display = xhandler->display();
    Window   window  = xhandler->window();
    XSelectInput(display, window,
                 KeyPressMask |
                 KeyReleaseMask |
                 StructureNotifyMask);

    Helicopter &helicopter = resources->heli_;
    KeySym key;
    XWindowAttributes attr;

    XEvent event;
    while (true) {
        XNextEvent(display, &event);

        if (pthread_mutex_lock(mutex) == -1) {
            error("cannot lock mutex in control thread");
        }

        switch (event.type) {
            case ConfigureNotify:
                if (event.xconfigure.width  != attr.width ||
                        event.xconfigure.height != attr.height) {
                    XGetWindowAttributes(display, window, &attr);

                    attr::DrawableBase::ScaleX = (double)PLANE_W / (double)attr.width;
                    attr::DrawableBase::ScaleY = (double)PLANE_H / (double)attr.height;

                    std::cout << attr::DrawableBase::ScaleX << std::endl;
                    std::cout << attr::DrawableBase::ScaleY << std::endl;
                    std::cout << "w: " << attr.width << std::endl;
                    std::cout << "h: " << attr.height << std::endl;

                    xhandler->updateAttr(&attr);
                }

                break;

            case KeyPress:
                XLookupString(&event.xkey, NULL, 0, &key, NULL);
                switch (key) {
                    case XK_f:
                        if (xhandler->showCredit()) {
                            xhandler->setShowCredit(false);
                        }
                        else {
                            xhandler->setShowCredit(true);
                        }
                        break;

                    case XK_Up:
                        helicopter.up_ = true;
                        break;
                    case XK_Down:
                        helicopter.down_ = true;
                        break;
                    case XK_Left:
                        helicopter.left_ = true;
                        break;
                    case XK_Right:
                        helicopter.right_ = true;
                        break;

                    case XK_a:
                        Tower::incSpeed();
                        Missile::incSpeed();
                        break;
                    case XK_z:
                        Tower::decSpeed();
                        Missile::decSpeed();
                        break;

                    /*
                    case XK_q:  // slow down scroll speed
                        Tower::incDelay(1);
                        Missile::incDelay(1);
                        Bomb::incDelay(2);
                        break;
                    case XK_w:  // speed up scroll speed
                        Tower::decDelay(1);
                        Missile::decDelay(1);
                        Bomb::decDelay(2);
                        break;

                    */
                    case XK_d:
                        if (helicopter.right_) {
                            int x = helicopter.x() + helicopter.w() * 0.8;
                            int y = helicopter.y() + helicopter.h() * 0.8;
                            resources->bombs_.addBomb(x,
                                                      y,
                                                      Bomb::FORWARD);
                        }
                        else if (helicopter.left_) {
                            int x = helicopter.x() + helicopter.w() * 0.8;
                            int y = helicopter.y() + helicopter.h() * 0.8;
                            resources->bombs_.addBomb(x,
                                                      y,
                                                      Bomb::BACKWARD);
                        }
                        else {
                            int x = helicopter.x() + helicopter.w() * 0.8;
                            int y = helicopter.y() + helicopter.h() * 0.8;
                            resources->bombs_.addBomb(x,
                                                      y,
                                                      Bomb::NUL);
                        }

                        /*
                        if (helicopter.movement() == Helicopter::LEFT) {
                            resources->bombs_.push_back(
                                    Bomb(
                                        helicopter.x() + Helicopter::w(),
                                        helicopter.y() + Helicopter::h(),
                                        false));
                        }
                        else {
                            resources->bombs_.push_back(
                                    Bomb(
                                        helicopter.x() + Helicopter::w(),
                                        helicopter.y() + Helicopter::h(),
                                        true));
                        }
                        */
                        break;

                    default:
                        break;
                }
                break;

            case KeyRelease:
                XLookupString(&event.xkey, NULL, 0, &key, NULL);
                switch (key) {
                    case XK_Up:
                        helicopter.up_ = false;
                        helicopter.delayUp_ = 30;
                        break;
                    case XK_Down:
                        helicopter.down_ = false;
                        helicopter.delayDown_ = 30;
                        break;
                    case XK_Left:
                        helicopter.left_ = false;
                        helicopter.delayLeft_ = 30;
                        break;
                    case XK_Right:
                        helicopter.right_ = false;
                        helicopter.delayRight_ = 30;
                        break;
                    default:
                        break;
                }
                break;

            default:
                break;

        }

        if (pthread_mutex_unlock(mutex) == -1) {
            error("cannot unlock mutex in control thread");
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x260, %rsp            # imm = 0x260
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rdi
callq 0x80f0
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rdi
callq 0x8110
movq (%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
movl $0x20003, %edx          # imm = 0x20003
callq 0x3130
movq -0x10(%rbp), %rax
addq $0x38, %rax
movq %rax, -0x38(%rbp)
movq -0x28(%rbp), %rdi
leaq -0x188(%rbp), %rsi
callq 0x3340
movq -0x20(%rbp), %rdi
callq 0x3360
cmpl $-0x1, %eax
jne 0x7af9
leaq -0x1a9(%rbp), %rdi
movq %rdi, -0x208(%rbp)
callq 0x3410
movq -0x208(%rbp), %rdx
leaq 0x57d0(%rip), %rsi      # 0xd250
leaq -0x1a8(%rbp), %rdi
callq 0x5430
jmp 0x7a8e
leaq -0x1a8(%rbp), %rdi
callq 0x53f0
jmp 0x7a9c
leaq -0x1a8(%rbp), %rdi
callq 0x3120
leaq -0x1a9(%rbp), %rdi
callq 0x3290
jmp 0x7af9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1b8(%rbp)
movl %eax, -0x1bc(%rbp)
jmp 0x7ae8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1b8(%rbp)
movl %eax, -0x1bc(%rbp)
leaq -0x1a8(%rbp), %rdi
callq 0x3120
leaq -0x1a9(%rbp), %rdi
callq 0x3290
jmp 0x80dd
movl -0x188(%rbp), %eax
movl %eax, -0x20c(%rbp)
subl $0x2, %eax
je 0x7c65
jmp 0x7b10
movl -0x20c(%rbp), %eax
subl $0x3, %eax
je 0x7f90
jmp 0x7b21
movl -0x20c(%rbp), %eax
subl $0x16, %eax
jne 0x802d
jmp 0x7b32
movl -0x150(%rbp), %eax
cmpl -0xc0(%rbp), %eax
jne 0x7b52
movl -0x14c(%rbp), %eax
cmpl -0xbc(%rbp), %eax
je 0x7c60
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
leaq -0xc8(%rbp), %rdx
callq 0x3420
cvtsi2sdl -0xc0(%rbp), %xmm1
movsd 0x54f2(%rip), %xmm0     # 0xd068
divsd %xmm1, %xmm0
leaq 0xb6f7(%rip), %rax      # 0x13278
movsd %xmm0, (%rax)
cvtsi2sdl -0xbc(%rbp), %xmm1
movsd 0x54db(%rip), %xmm0     # 0xd070
divsd %xmm1, %xmm0
leaq 0xb6e0(%rip), %rax      # 0x13280
movsd %xmm0, (%rax)
leaq 0xb6cd(%rip), %rax      # 0x13278
movsd (%rax), %xmm0
movq 0xb412(%rip), %rdi      # 0x12fc8
callq 0x3460
movq %rax, %rdi
movq 0xb3db(%rip), %rsi      # 0x12fa0
callq 0x3270
leaq 0xb6af(%rip), %rax      # 0x13280
movsd (%rax), %xmm0
movq 0xb3ec(%rip), %rdi      # 0x12fc8
callq 0x3460
movq %rax, %rdi
movq 0xb3b5(%rip), %rsi      # 0x12fa0
callq 0x3270
movq 0xb3d1(%rip), %rdi      # 0x12fc8
leaq 0x5676(%rip), %rsi      # 0xd274
callq 0x3230
movq %rax, %rdi
movl -0xc0(%rbp), %esi
callq 0x33f0
movq %rax, %rdi
movq 0xb385(%rip), %rsi      # 0x12fa0
callq 0x3270
movq 0xb3a1(%rip), %rdi      # 0x12fc8
leaq 0x564a(%rip), %rsi      # 0xd278
callq 0x3230
movq %rax, %rdi
movl -0xbc(%rbp), %esi
callq 0x33f0
movq %rax, %rdi
movq 0xb355(%rip), %rsi      # 0x12fa0
callq 0x3270
movq -0x18(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x7520
jmp 0x802f
xorl %edx, %edx
movl %edx, %r8d
leaq -0x188(%rbp), %rdi
leaq -0x40(%rbp), %rcx
movq %r8, %rsi
callq 0x31e0
movq -0x40(%rbp), %rax
movq %rax, -0x218(%rbp)
subq $0x61, %rax
je 0x7d76
jmp 0x7c94
movq -0x218(%rbp), %rax
subq $0x64, %rax
je 0x7d94
jmp 0x7ca7
movq -0x218(%rbp), %rax
subq $0x66, %rax
je 0x7d14
jmp 0x7cb6
movq -0x218(%rbp), %rax
subq $0x7a, %rax
je 0x7d85
jmp 0x7cc9
movq -0x218(%rbp), %rax
subq $0xff51, %rax           # imm = 0xFF51
je 0x7d5c
jmp 0x7cde
movq -0x218(%rbp), %rax
subq $0xff52, %rax           # imm = 0xFF52
je 0x7d43
jmp 0x7cef
movq -0x218(%rbp), %rax
subq $0xff53, %rax           # imm = 0xFF53
je 0x7d69
jmp 0x7d00
movq -0x218(%rbp), %rax
subq $0xff54, %rax           # imm = 0xFF54
je 0x7d4f
jmp 0x7f89
movq -0x18(%rbp), %rdi
callq 0x8130
testb $0x1, %al
jne 0x7d23
jmp 0x7d30
movq -0x18(%rbp), %rdi
xorl %esi, %esi
callq 0x3c90
jmp 0x7d3e
movq -0x18(%rbp), %rdi
movl $0x1, %esi
callq 0x3c90
jmp 0x7f8b
movq -0x38(%rbp), %rax
movb $0x1, (%rax)
jmp 0x7f8b
movq -0x38(%rbp), %rax
movb $0x1, 0x1(%rax)
jmp 0x7f8b
movq -0x38(%rbp), %rax
movb $0x1, 0x2(%rax)
jmp 0x7f8b
movq -0x38(%rbp), %rax
movb $0x1, 0x3(%rax)
jmp 0x7f8b
callq 0x8150
callq 0x8180
jmp 0x7f8b
callq 0x81b0
callq 0x81e0
jmp 0x7f8b
movq -0x38(%rbp), %rax
testb $0x1, 0x3(%rax)
je 0x7e41
movq -0x38(%rbp), %rdi
callq 0x8210
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x228(%rbp)
callq 0x8230
movsd -0x228(%rbp), %xmm1
cvtsi2sd %eax, %xmm0
movsd 0x5468(%rip), %xmm2     # 0xd238
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x1c0(%rbp)
movq -0x38(%rbp), %rdi
callq 0x8240
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x220(%rbp)
callq 0x8260
movsd -0x220(%rbp), %xmm1
cvtsi2sd %eax, %xmm0
movsd 0x5428(%rip), %xmm2     # 0xd238
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x1c4(%rbp)
movq -0x10(%rbp), %rdi
movl -0x1c0(%rbp), %esi
movl -0x1c4(%rbp), %edx
movl $0x1, %ecx
callq 0xa6c0
jmp 0x7f87
movq -0x38(%rbp), %rax
testb $0x1, 0x2(%rax)
je 0x7eee
movq -0x38(%rbp), %rdi
callq 0x8210
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x238(%rbp)
callq 0x8230
movsd -0x238(%rbp), %xmm1
cvtsi2sd %eax, %xmm0
movsd 0x53bb(%rip), %xmm2     # 0xd238
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x1c8(%rbp)
movq -0x38(%rbp), %rdi
callq 0x8240
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x230(%rbp)
callq 0x8260
movsd -0x230(%rbp), %xmm1
cvtsi2sd %eax, %xmm0
movsd 0x537b(%rip), %xmm2     # 0xd238
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x1cc(%rbp)
movq -0x10(%rbp), %rdi
movl -0x1c8(%rbp), %esi
movl -0x1cc(%rbp), %edx
movl $0x2, %ecx
callq 0xa6c0
jmp 0x7f85
movq -0x38(%rbp), %rdi
callq 0x8210
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x248(%rbp)
callq 0x8230
movsd -0x248(%rbp), %xmm1
cvtsi2sd %eax, %xmm0
movsd 0x531c(%rip), %xmm2     # 0xd238
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x1d0(%rbp)
movq -0x38(%rbp), %rdi
callq 0x8240
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x240(%rbp)
callq 0x8260
movsd -0x240(%rbp), %xmm1
cvtsi2sd %eax, %xmm0
movsd 0x52dc(%rip), %xmm2     # 0xd238
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x1d4(%rbp)
movq -0x10(%rbp), %rdi
movl -0x1d0(%rbp), %esi
movl -0x1d4(%rbp), %edx
xorl %ecx, %ecx
callq 0xa6c0
jmp 0x7f87
jmp 0x7f8b
jmp 0x7f8b
jmp 0x802f
xorl %edx, %edx
movl %edx, %r8d
leaq -0x188(%rbp), %rdi
leaq -0x40(%rbp), %rcx
movq %r8, %rsi
callq 0x31e0
movq -0x40(%rbp), %rax
addq $-0xff51, %rax          # imm = 0xFFFF00AF
movq %rax, -0x250(%rbp)
subq $0x3, %rax
ja 0x8029
movq -0x250(%rbp), %rax
leaq 0x5273(%rip), %rcx      # 0xd240
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x38(%rbp), %rax
movb $0x0, (%rax)
movq -0x38(%rbp), %rax
movl $0x1e, 0x4(%rax)
jmp 0x802b
movq -0x38(%rbp), %rax
movb $0x0, 0x1(%rax)
movq -0x38(%rbp), %rax
movl $0x1e, 0x8(%rax)
jmp 0x802b
movq -0x38(%rbp), %rax
movb $0x0, 0x2(%rax)
movq -0x38(%rbp), %rax
movl $0x1e, 0xc(%rax)
jmp 0x802b
movq -0x38(%rbp), %rax
movb $0x0, 0x3(%rax)
movq -0x38(%rbp), %rax
movl $0x1e, 0x10(%rax)
jmp 0x802b
jmp 0x802b
jmp 0x802f
jmp 0x802f
movq -0x20(%rbp), %rdi
callq 0x3180
cmpl $-0x1, %eax
jne 0x80d8
leaq -0x1f9(%rbp), %rdi
movq %rdi, -0x258(%rbp)
callq 0x3410
movq -0x258(%rbp), %rdx
leaq 0x521a(%rip), %rsi      # 0xd27c
leaq -0x1f8(%rbp), %rdi
callq 0x5430
jmp 0x8070
leaq -0x1f8(%rbp), %rdi
callq 0x53f0
jmp 0x807e
leaq -0x1f8(%rbp), %rdi
callq 0x3120
leaq -0x1f9(%rbp), %rdi
callq 0x3290
jmp 0x80d8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1b8(%rbp)
movl %eax, -0x1bc(%rbp)
jmp 0x80ca
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1b8(%rbp)
movl %eax, -0x1bc(%rbp)
leaq -0x1f8(%rbp), %rdi
callq 0x3120
leaq -0x1f9(%rbp), %rdi
callq 0x3290
jmp 0x80dd
jmp 0x7a3d
movq -0x1b8(%rbp), %rdi
callq 0x3400
nopl (%rax)