// File: ryanbarringtoncox[P]AVLTree/AVLTree.cpp
// Function: AVLTree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>::insert(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
void AVLTree<T>::insert(T v) {
	Node<T>* temp = new Node<T>(v);
	Node<T>** curr = &root;

	//double rotation flags
	bool rightLeft = false;
	bool leftRight = false;
	
	//tree is empty, insert at root
	if (*curr == 0) {
		*curr = temp;			
	}
	
	else {

		//keep a parent pointer
		Node<T>** dad = &root;
		
		//Critical node is null by default
		cn = 0;
		
		//find spot for new node, keep track of potential cns
		while (*curr != 0) {
			
			if (v == (*curr)->getValue()) return;
			
			if (v < (*curr)->getValue()) {
				if ((*curr)->getBalance() == -1) {
					cn = *curr;
					dad = &*curr;
				}
				if (cn && cn->getBalance() > 0) {
					cout << "Rotate right then left" << endl;
					rightLeft = true;
				}
				curr = &((*curr)->getLeftChild());
			} else if (v > (*curr)->getValue()) {
				if ((*curr)->getBalance() == 1) {
					cn = *curr;	
					dad = &*curr;
				}
				if (cn && cn->getBalance() < 0) {
					cout << "Rotate left then right" << endl;
					leftRight = true;
				}
				curr = &((*curr)->getRightChild());
			}
		}
		
		//insert the node
		*curr = temp;	
		
		
		//no cn, update balances
		if (!cn) {			
			curr = &root;
			while (*curr != 0) {
				if (v < (*curr)->getValue()) {
					(*curr)->decBalance();
					curr = &((*curr)->getLeftChild());
				} else if (v > (*curr)->getValue()) {
					(*curr)->incBalance();					
					curr = &((*curr)->getRightChild());
				}
				else if (v == (*curr)->getValue()) break;
			}			
		}		
		
		//single rotations
		if (cn && !rightLeft && !leftRight) {			
			//cout << "Cn found: " << cn->getValue() << endl;
			curr = &cn;
			
			if ((*curr)->getBalance() == -1) {	
				rightRotation(cn, dad);
			}
			
			if ((*curr)->getBalance()== 1) {	
				leftRotation(cn, dad);
			}
			
			//reset cn balance to zero
			cn->resetBalance();			
			
		}
			
		//double rotations
		if (cn && rightLeft) {
			rightRotation(cn->getRightChild(), &(cn->getRightChild()));
			leftRotation(cn, dad);
			cn->resetBalance();
		}
		if (cn && leftRight) {
			leftRotation(cn->getLeftChild(), &(cn->getLeftChild()));
			rightRotation(cn, dad);
			cn->resetBalance();
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x150, %rsp            # imm = 0x150
movq %rsi, -0x130(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x138(%rbp)
movl $0x40, %edi
callq 0x21b0
movq -0x130(%rbp), %rsi
movq %rax, -0x128(%rbp)
movb $0x1, -0x45(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x20a0
jmp 0x892c
movq -0x128(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0xceb0
jmp 0x893e
movb $0x0, -0x45(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x2100
movq -0x128(%rbp), %rcx
movq -0x138(%rbp), %rax
movq %rcx, -0x18(%rbp)
movq %rax, -0x50(%rbp)
movb $0x0, -0x51(%rbp)
movb $0x0, -0x52(%rbp)
movq -0x50(%rbp), %rax
cmpq $0x0, (%rax)
jne 0x89c4
movq -0x18(%rbp), %rcx
movq -0x50(%rbp), %rax
movq %rcx, (%rax)
jmp 0x8e90
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x89a6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x2100
testb $0x1, -0x45(%rbp)
jne 0x89ae
jmp 0x89bf
movq -0x128(%rbp), %rdi
movl $0x40, %esi
callq 0x21c0
jmp 0x8e99
movq -0x138(%rbp), %rax
movq %rax, -0x60(%rbp)
movq $0x0, 0x8(%rax)
movq -0x50(%rbp), %rax
cmpq $0x0, (%rax)
je 0x8bc7
movq -0x50(%rbp), %rax
movq (%rax), %rsi
leaq -0x80(%rbp), %rdi
callq 0xcf30
movq -0x130(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x8eb0
movb %al, -0x139(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x2100
movb -0x139(%rbp), %al
testb $0x1, %al
jne 0x8a20
jmp 0x8a25
jmp 0x8e90
movq -0x50(%rbp), %rax
movq (%rax), %rsi
leaq -0xa0(%rbp), %rdi
callq 0xcf30
movq -0x130(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x8020
movb %al, -0x13a(%rbp)
leaq -0xa0(%rbp), %rdi
callq 0x2100
movb -0x13a(%rbp), %al
testb $0x1, %al
jne 0x8a6c
jmp 0x8af5
movq -0x50(%rbp), %rax
movq (%rax), %rdi
callq 0xcf60
cmpl $-0x1, %eax
jne 0x8a97
movq -0x138(%rbp), %rax
movq -0x50(%rbp), %rcx
movq (%rcx), %rcx
movq %rcx, 0x8(%rax)
movq -0x50(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x138(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x8ae0
movq -0x138(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xcf60
cmpl $0x0, %eax
jle 0x8ae0
movq 0x15517(%rip), %rdi     # 0x1dfd8
leaq 0xb6e0(%rip), %rsi      # 0x141a8
callq 0x21a0
movq %rax, %rdi
movq 0x154f1(%rip), %rsi     # 0x1dfc8
callq 0x21d0
movb $0x1, -0x51(%rbp)
movq -0x50(%rbp), %rax
movq (%rax), %rdi
callq 0xd000
movq %rax, -0x50(%rbp)
jmp 0x8bc2
movq -0x50(%rbp), %rax
movq (%rax), %rsi
leaq -0xc0(%rbp), %rdi
callq 0xcf30
movq -0x130(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x8060
movb %al, -0x13b(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x2100
movb -0x13b(%rbp), %al
testb $0x1, %al
jne 0x8b3c
jmp 0x8bc0
movq -0x50(%rbp), %rax
movq (%rax), %rdi
callq 0xcf60
cmpl $0x1, %eax
jne 0x8b67
movq -0x138(%rbp), %rax
movq -0x50(%rbp), %rcx
movq (%rcx), %rcx
movq %rcx, 0x8(%rax)
movq -0x50(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x138(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x8bb0
movq -0x138(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xcf60
cmpl $0x0, %eax
jge 0x8bb0
movq 0x15447(%rip), %rdi     # 0x1dfd8
leaq 0xb627(%rip), %rsi      # 0x141bf
callq 0x21a0
movq %rax, %rdi
movq 0x15421(%rip), %rsi     # 0x1dfc8
callq 0x21d0
movb $0x1, -0x52(%rbp)
movq -0x50(%rbp), %rax
movq (%rax), %rdi
callq 0xd040
movq %rax, -0x50(%rbp)
jmp 0x8bc2
jmp 0x89d7
movq -0x138(%rbp), %rax
movq -0x18(%rbp), %rdx
movq -0x50(%rbp), %rcx
movq %rdx, (%rcx)
cmpq $0x0, 0x8(%rax)
jne 0x8d15
movq -0x138(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
cmpq $0x0, (%rax)
je 0x8d13
movq -0x50(%rbp), %rax
movq (%rax), %rsi
leaq -0xe0(%rbp), %rdi
callq 0xcf30
movq -0x130(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x8020
movb %al, -0x13c(%rbp)
leaq -0xe0(%rbp), %rdi
callq 0x2100
movb -0x13c(%rbp), %al
testb $0x1, %al
jne 0x8c41
jmp 0x8c62
movq -0x50(%rbp), %rax
movq (%rax), %rdi
callq 0xcfa0
movq -0x50(%rbp), %rax
movq (%rax), %rdi
callq 0xd000
movq %rax, -0x50(%rbp)
jmp 0x8d0e
movq -0x50(%rbp), %rax
movq (%rax), %rsi
leaq -0x100(%rbp), %rdi
callq 0xcf30
movq -0x130(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0x8060
movb %al, -0x13d(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x2100
movb -0x13d(%rbp), %al
testb $0x1, %al
jne 0x8ca6
jmp 0x8cc4
movq -0x50(%rbp), %rax
movq (%rax), %rdi
callq 0xcf80
movq -0x50(%rbp), %rax
movq (%rax), %rdi
callq 0xd040
movq %rax, -0x50(%rbp)
jmp 0x8d0c
movq -0x50(%rbp), %rax
movq (%rax), %rsi
leaq -0x120(%rbp), %rdi
callq 0xcf30
movq -0x130(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x8eb0
movb %al, -0x13e(%rbp)
leaq -0x120(%rbp), %rdi
callq 0x2100
movb -0x13e(%rbp), %al
testb $0x1, %al
jne 0x8d08
jmp 0x8d0a
jmp 0x8d13
jmp 0x8d0c
jmp 0x8d0e
jmp 0x8bef
jmp 0x8d15
movq -0x138(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x8d98
testb $0x1, -0x51(%rbp)
jne 0x8d98
testb $0x1, -0x52(%rbp)
jne 0x8d98
movq -0x138(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq (%rax), %rdi
callq 0xcf60
cmpl $-0x1, %eax
jne 0x8d63
movq -0x138(%rbp), %rdi
movq 0x8(%rdi), %rsi
movq -0x60(%rbp), %rdx
callq 0x7d60
movq -0x50(%rbp), %rax
movq (%rax), %rdi
callq 0xcf60
cmpl $0x1, %eax
jne 0x8d88
movq -0x138(%rbp), %rdi
movq 0x8(%rdi), %rsi
movq -0x60(%rbp), %rdx
callq 0x7c60
movq -0x138(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xcfc0
movq -0x138(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x8e13
testb $0x1, -0x51(%rbp)
je 0x8e13
movq -0x138(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xd040
movq %rax, %rcx
movq -0x138(%rbp), %rax
movq (%rcx), %rcx
movq %rcx, -0x148(%rbp)
movq 0x8(%rax), %rdi
callq 0xd040
movq -0x148(%rbp), %rsi
movq -0x138(%rbp), %rdi
movq %rax, %rdx
callq 0x7d60
movq -0x138(%rbp), %rdi
movq 0x8(%rdi), %rsi
movq -0x60(%rbp), %rdx
callq 0x7c60
movq -0x138(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xcfc0
movq -0x138(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x8e8e
testb $0x1, -0x52(%rbp)
je 0x8e8e
movq -0x138(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xd000
movq %rax, %rcx
movq -0x138(%rbp), %rax
movq (%rcx), %rcx
movq %rcx, -0x150(%rbp)
movq 0x8(%rax), %rdi
callq 0xd000
movq -0x150(%rbp), %rsi
movq -0x138(%rbp), %rdi
movq %rax, %rdx
callq 0x7c60
movq -0x138(%rbp), %rdi
movq 0x8(%rdi), %rsi
movq -0x60(%rbp), %rdx
callq 0x7d60
movq -0x138(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xcfc0
jmp 0x8e90
addq $0x150, %rsp            # imm = 0x150
popq %rbp
retq
movq -0x40(%rbp), %rdi
callq 0x22c0
nopw %cs:(%rax,%rax)
nopl (%rax)