// File: /workspace/github_cpp_makefile_star2_O1/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rsi, %r12
movss %xmm0, -0x30(%rbp)
movq %rdi, -0x38(%rbp)
cmpq $0x0, 0x8(%rdi)
je 0x3096
movl $0x4, %edi
callq 0x2170
movq %rax, -0x40(%rbp)
movl $0x50, %edi
callq 0x2170
movq %rax, %r14
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movups %xmm0, 0x10(%rax)
movups %xmm0, 0x20(%rax)
movups %xmm0, 0x30(%rax)
movups %xmm0, 0x40(%rax)
movq %rax, %rdi
xorl %esi, %esi
callq 0x3cc2
movq -0x38(%rbp), %rdi
movq 0x8(%rdi), %rsi
movss -0x30(%rbp), %xmm0
movq %r14, %rdx
callq 0x2d00
movq 0x30(%r14), %rax
cmpq 0x38(%r14), %rax
jne 0x2f7f
movq 0x48(%r14), %rcx
movl $0x200, %eax            # imm = 0x200
addq -0x8(%rcx), %rax
movq -0x8(%rax), %rbx
leaq -0x68(%rbp), %r15
movq %r15, -0x10(%r15)
movq (%r12), %rsi
movq 0x8(%r12), %rdx
addq %rsi, %rdx
leaq -0x78(%rbp), %r12
movq %r12, %rdi
callq 0x2c66
movq (%rbx), %rax
movq %rbx, %rdi
movss -0x30(%rbp), %xmm0
movq %r12, %rsi
callq *(%rax)
movq -0x78(%rbp), %rdi
cmpq %r15, %rdi
je 0x2fc1
callq 0x2150
xorl %r13d, %r13d
xorl %r12d, %r12d
movq %r13, -0x30(%rbp)
movq 0x30(%r14), %rax
cmpq 0x38(%r14), %rax
jne 0x2fe5
movq 0x48(%r14), %rax
movq -0x8(%rax), %rax
movl $0x200, %ecx            # imm = 0x200
addq %rcx, %rax
movq -0x8(%rax), %rsi
leaq -0x58(%rbp), %rdi
callq 0x3eca
movq -0x58(%rbp), %rbx
movq -0x50(%rbp), %r15
movq -0x38(%rbp), %rax
movslq (%rax), %r13
testq %rbx, %rbx
je 0x300e
movq %rbx, %rdi
callq 0x2150
subq %rbx, %r15
sarq $0x2, %r15
movq %r13, %rbx
cmpq %r13, %r15
jne 0x30fb
movq 0x30(%r14), %rax
cmpq 0x38(%r14), %rax
jne 0x303b
movq 0x48(%r14), %rax
movq -0x8(%rax), %rax
movl $0x200, %ecx            # imm = 0x200
addq %rcx, %rax
movq -0x8(%rax), %r12
movq (%r12), %rax
movq %r12, %rdi
movq -0x40(%rbp), %rsi
callq *0x28(%rax)
movq %rax, %r13
movq %r14, %rdi
callq 0x3e1e
movq 0x30(%r14), %rax
cmpq 0x10(%r14), %rax
je 0x30f7
cmpq 0x38(%r14), %rax
jne 0x307c
movq 0x48(%r14), %rax
movq -0x8(%rax), %rax
movl $0x200, %ecx            # imm = 0x200
addq %rcx, %rax
movq -0x8(%rax), %rdi
movq -0x40(%rbp), %rax
movss (%rax), %xmm0
movq (%rdi), %rax
movq %r13, %rsi
callq *0x8(%rax)
jmp 0x2fc7
movl $0x50, %edi
callq 0x2170
movq %rax, %r14
movq %rax, %rdi
callq 0x481c
movq -0x38(%rbp), %rax
movq %r14, 0x8(%rax)
leaq -0x88(%rbp), %r15
movq %r15, -0x10(%r15)
movq (%r12), %rsi
movq 0x8(%r12), %rdx
addq %rsi, %rdx
leaq -0x98(%rbp), %rbx
movq %rbx, %rdi
callq 0x2c66
movq (%r14), %rax
movq %r14, %rdi
movss -0x30(%rbp), %xmm0
movq %rbx, %rsi
callq *(%rax)
movq -0x98(%rbp), %rdi
cmpq %r15, %rdi
jne 0x3149
jmp 0x314e
movq %r13, -0x30(%rbp)
cmpq %rbx, %r15
jne 0x3135
movl $0x40, %edi
callq 0x2170
movq %rax, %r15
movq %rax, %rdi
callq 0x3f84
movq -0x40(%rbp), %rax
movss (%rax), %xmm0
movq (%r15), %rax
movq %r15, %rdi
movq %r12, %rsi
movq -0x30(%rbp), %rdx
callq *0x10(%rax)
movq -0x38(%rbp), %rax
movq %r15, 0x8(%rax)
movq -0x40(%rbp), %rdi
callq 0x2150
movq %r14, %rdi
callq 0x3a4c
movq %r14, %rdi
callq 0x2150
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
movq %r15, %rdi
jmp 0x3187
movq %rax, %rbx
movq -0x98(%rbp), %rdi
jmp 0x317a
jmp 0x3181
movq %rax, %rbx
movq -0x78(%rbp), %rdi
cmpq %r15, %rdi
jne 0x3187
jmp 0x318c
movq %rax, %rbx
movq %r14, %rdi
callq 0x2150
movq %rbx, %rdi
callq 0x22a0