// File: deepaktabraham[P]BPlus-Tree/src/tree.cpp
// Function: BPlusTree::Insert(float, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
void BPlusTree :: Insert(float key, string value)
{
	// check if tree is empty
	if(NULL == root)
	{
		// Irrespective of the order, root is always a leaf node for 
		// the first insertion. So, create a new leaf node.
		root = new LeafNode;
		root->Insert(key, value);
	}

	// if it is a subsequent insertion
	else
	{
		Node* leftNode = NULL;
		Node* rightNode = NULL;
		float* keyToParent = new float;
		bool rootPopped = false;
		
		// obtain the search path from the root to leaf node and push it on to a stack
		stack<Node*>* path = new stack<Node*>;
		Search_Path(root, key, path);

		// insert the key-value pair in the leaf node
		path->top()->Insert(key, value);

		// Split the current node and insert the middle key & children in to the parent. Perform
		// this as long as there is an imbalance in the tree, moving up the stack every iteration.
		while(path->top()->Get_Keys().size() == order)
		{
			// Update the current node as the left half and return the right half. Also 
			// obtain the middle element, which is the key to be moved up to the parent.
			leftNode = path->top();
			rightNode = leftNode->Split(keyToParent);

			// check if currently split node is not the root node
			path->pop();
			if(!path->empty())
			{
				// Insert the middle key and the right half in to 
				// the parent. The parent will be an internal node.
				path->top()->Insert(*keyToParent, rightNode);
			}

			// if currently split node is the root node
			else
			{
				// set flag indicating that the root has popped from the stack
				rootPopped = true;
				break;
			}
		}

		// new internal node needs to be created and assigned as the root
		if(rootPopped)
		{
			// create a new internal node
			InternalNode* tempRoot = new InternalNode;

			// insert the left and the right halves as the children of this new internal node
			tempRoot->Insert(*keyToParent, leftNode, rightNode);

			// mark this new internal node as the root of the tree
			root = tempRoot;
		}

		delete(keyToParent);
		delete(path);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movq %rsi, -0xc0(%rbp)
movq %rdi, -0x8(%rbp)
movss %xmm0, -0xc(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x8(%rbp), %rcx
movq %rcx, -0xb8(%rbp)
xorl %eax, %eax
cmpq 0x8(%rcx), %rax
jne 0x32aa
movl $0x50, %edi
callq 0x21a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xc8(%rbp)
callq 0xadb0
jmp 0x3204
movq -0xc0(%rbp), %rsi
movq -0xb8(%rbp), %rax
movq -0xc8(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x8(%rax), %rax
movq %rax, -0xe0(%rbp)
movss -0xc(%rbp), %xmm0
movss %xmm0, -0xd4(%rbp)
leaq -0x48(%rbp), %rdi
movq %rdi, -0xd0(%rbp)
callq 0x20c0
movq -0xe0(%rbp), %rdi
movss -0xd4(%rbp), %xmm0
movq -0xd0(%rbp), %rsi
movq (%rdi), %rax
movq (%rax), %rax
callq *%rax
jmp 0x3265
leaq -0x48(%rbp), %rdi
callq 0x2120
jmp 0x3538
movq -0xc8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x2180
jmp 0x3541
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x2120
jmp 0x3541
movq $0x0, -0x50(%rbp)
movq $0x0, -0x58(%rbp)
movl $0x4, %edi
callq 0x21a0
movq %rax, -0x60(%rbp)
movb $0x0, -0x61(%rbp)
movl $0x50, %edi
callq 0x21a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xe8(%rbp)
callq 0x4430
jmp 0x32ea
movq -0xb8(%rbp), %rdi
movq -0xe8(%rbp), %rax
movq %rax, -0x70(%rbp)
movq 0x8(%rdi), %rsi
movss -0xc(%rbp), %xmm0
movq -0x70(%rbp), %rdx
callq 0x2ed0
movq -0x70(%rbp), %rdi
callq 0x4460
movq -0xc0(%rbp), %rsi
movq (%rax), %rax
movq %rax, -0x100(%rbp)
movss -0xc(%rbp), %xmm0
movss %xmm0, -0xf4(%rbp)
leaq -0x90(%rbp), %rdi
movq %rdi, -0xf0(%rbp)
callq 0x20c0
movq -0x100(%rbp), %rdi
movss -0xf4(%rbp), %xmm0
movq -0xf0(%rbp), %rsi
movq (%rdi), %rax
movq (%rax), %rax
callq *%rax
jmp 0x3368
leaq -0x90(%rbp), %rdi
callq 0x2120
movq -0x70(%rbp), %rdi
callq 0x4460
movq (%rax), %rsi
leaq -0xa8(%rbp), %rdi
callq 0x6c60
leaq -0xa8(%rbp), %rdi
callq 0x4480
movq %rax, %rcx
movq -0xb8(%rbp), %rax
movq %rcx, -0x108(%rbp)
movslq (%rax), %rax
movq %rax, -0x110(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x42a0
movq -0x110(%rbp), %rcx
movq -0x108(%rbp), %rax
cmpq %rcx, %rax
jne 0x3473
movq -0x70(%rbp), %rdi
callq 0x4460
movq (%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
movq -0x60(%rbp), %rsi
movq (%rdi), %rax
callq *0x28(%rax)
movq %rax, -0x58(%rbp)
movq -0x70(%rbp), %rdi
callq 0x44a0
movq -0x70(%rbp), %rdi
callq 0x44c0
testb $0x1, %al
jne 0x3468
movq -0x70(%rbp), %rdi
callq 0x4460
movq (%rax), %rdi
movq -0x60(%rbp), %rax
movss (%rax), %xmm0
movq -0x58(%rbp), %rsi
movq (%rdi), %rax
callq *0x8(%rax)
jmp 0x346e
movq -0xe8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x2180
jmp 0x3541
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x2120
jmp 0x3541
movb $0x1, -0x61(%rbp)
jmp 0x3473
jmp 0x3374
testb $0x1, -0x61(%rbp)
je 0x34f0
movl $0x40, %edi
callq 0x21a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x118(%rbp)
callq 0x72e0
jmp 0x3497
movq -0x118(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rdi
movq -0x60(%rbp), %rax
movss (%rax), %xmm0
movq -0x50(%rbp), %rsi
movq -0x58(%rbp), %rdx
movq (%rdi), %rax
callq *0x10(%rax)
movq -0xb8(%rbp), %rax
movq -0xb0(%rbp), %rcx
movq %rcx, 0x8(%rax)
jmp 0x34f0
movq -0x118(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x2180
jmp 0x3541
movq -0x60(%rbp), %rax
movq %rax, -0x120(%rbp)
cmpq $0x0, %rax
je 0x350d
movq -0x120(%rbp), %rdi
callq 0x2180
movq -0x70(%rbp), %rax
movq %rax, -0x128(%rbp)
cmpq $0x0, %rax
je 0x3536
movq -0x128(%rbp), %rdi
callq 0x44e0
movq -0x128(%rbp), %rdi
callq 0x2180
jmp 0x3538
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
movq -0x20(%rbp), %rdi
callq 0x22d0
nopw (%rax,%rax)