// File: dvjdjvu[P]bntree/./src/bntree.cpp
// Function: bntree::erase(unsigned long)
void bntree::erase(uint64_t index) {

    if (index < 0 || index > this->size() - 1) {
        return;
    }

    node_t *search_node = this->tree->root;
    uint64_t index_node = this->get_child_weight(search_node->left);

    for (;;) {
        if (index == index_node) {
            if (this->erase_simple(search_node)) {
                // pass
            } else if (search_node->left && search_node->right) {
                // Самый сложный случай, удаляемый узел имеет 2-х детей.

                node_t *del_node = search_node;
                uint64_t _index;
                // Маленькая балансировка, если правый вес больше левого то удаляем через право
                // иначе через лево
                if (search_node->right->weight > search_node->left->weight) {
                    _index = index_node + 1;
                } else {
                    _index = index_node - 1;
                }

                // Ищем узел со следующим индексом.
                for (;;) {
                    if (_index == index_node) {
                        // Узел найден
                        break;
                    } else if (_index > index_node) {
                        search_node->weight--;
                        search_node = search_node->right;
                        index_node += (this->get_child_weight(search_node->left) + 1);
                    } else {
                        search_node->weight--;
                        search_node = search_node->left;
                        index_node -= (this->get_child_weight(search_node->right) + 1);
                    }
                }

                del_node->data = search_node->data;
                this->erase_simple(search_node);
            }

            this->node_free(search_node);

            return;
        } else if (index > index_node) {
            search_node->weight--;
            search_node = search_node->right;
            index_node += (this->get_child_weight(search_node->left) + 1);
        } else {
            search_node->weight--;
            search_node = search_node->left;
            index_node -= (this->get_child_weight(search_node->right) + 1);
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x10(%rbp)
jb 0x2ec0
movq -0x38(%rbp), %rdi
movq -0x10(%rbp), %rax
movq %rax, -0x40(%rbp)
callq 0x30c0
movq %rax, %rcx
movq -0x40(%rbp), %rax
subq $0x1, %rcx
cmpq %rcx, %rax
jbe 0x2ec5
jmp 0x30b9
movq -0x38(%rbp), %rdi
movq (%rdi), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rsi
callq 0x2700
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
cmpq -0x20(%rbp), %rax
jne 0x302e
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x2c80
testb $0x1, %al
jne 0x2f05
jmp 0x2f0a
jmp 0x301c
movq -0x18(%rbp), %rax
cmpq $0x0, 0x48(%rax)
je 0x301a
movq -0x18(%rbp), %rax
cmpq $0x0, 0x50(%rax)
je 0x301a
movq -0x18(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rax
movq 0x40(%rax), %rax
movq -0x18(%rbp), %rcx
movq 0x48(%rcx), %rcx
cmpq 0x40(%rcx), %rax
jbe 0x2f58
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
jmp 0x2f64
movq -0x20(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x30(%rbp)
jmp 0x2f66
movq -0x30(%rbp), %rax
cmpq -0x20(%rbp), %rax
jne 0x2f75
jmp 0x3000
movq -0x30(%rbp), %rax
cmpq -0x20(%rbp), %rax
jbe 0x2fba
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x40(%rax), %rcx
addq $-0x1, %rcx
movq %rcx, 0x40(%rax)
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rsi
callq 0x2700
addq $0x1, %rax
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x2ff9
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x40(%rax), %rcx
addq $-0x1, %rcx
movq %rcx, 0x40(%rax)
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rsi
callq 0x2700
movq %rax, %rcx
addq $0x1, %rcx
movq -0x20(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x20(%rbp)
jmp 0x2ffb
jmp 0x2f66
movq -0x18(%rbp), %rsi
movq -0x28(%rbp), %rdi
callq 0x3950
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x2c80
jmp 0x301c
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x25a0
jmp 0x30b9
movq -0x10(%rbp), %rax
cmpq -0x20(%rbp), %rax
jbe 0x3073
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x40(%rax), %rcx
addq $-0x1, %rcx
movq %rcx, 0x40(%rax)
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rsi
callq 0x2700
addq $0x1, %rax
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x30b2
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x40(%rax), %rcx
addq $-0x1, %rcx
movq %rcx, 0x40(%rax)
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rsi
callq 0x2700
movq %rax, %rcx
addq $0x1, %rcx
movq -0x20(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x20(%rbp)
jmp 0x30b4
jmp 0x2ee4
addq $0x40, %rsp
popq %rbp
retq
nop