// File: /workspace/github_cpp_makefile_star2_O2/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 $0x68, %rsp
movq %rsi, %r12
movss %xmm0, -0x2c(%rbp)
movq %rdi, -0x38(%rbp)
cmpq $0x0, 0x8(%rdi)
je 0x2d12
pushq $0x4
popq %rdi
callq 0x2150
movq %rax, %r15
pushq $0x50
popq %rdi
callq 0x2150
movq %rax, %r14
movq %rax, %rdi
callq 0x33aa
movq -0x38(%rbp), %rdi
movq 0x8(%rdi), %rsi
movss -0x2c(%rbp), %xmm0
movq %r14, %rdx
callq 0x2a48
movq 0x30(%r14), %rax
cmpq 0x38(%r14), %rax
jne 0x2c2c
movq 0x48(%r14), %rcx
movl $0x200, %eax            # imm = 0x200
addq -0x8(%rcx), %rax
movq -0x8(%rax), %rbx
leaq -0x70(%rbp), %r13
movq %r13, %rdi
movq %r12, %rsi
callq 0x21d0
movq (%rbx), %rax
movq %rbx, %rdi
movss -0x2c(%rbp), %xmm0
movq %r13, %rsi
callq *(%rax)
leaq -0x70(%rbp), %rdi
callq 0x20a0
leaq -0x50(%rbp), %r12
movq 0x30(%r14), %rax
cmpq 0x38(%r14), %rax
jne 0x2c76
movq 0x48(%r14), %rax
movq -0x8(%rax), %rax
movl $0x200, %ecx            # imm = 0x200
addq %rcx, %rax
movq -0x8(%rax), %rsi
movq %r12, %rdi
callq 0x3b06
movq -0x48(%rbp), %rbx
subq -0x50(%rbp), %rbx
sarq $0x2, %rbx
movq -0x38(%rbp), %rax
movslq (%rax), %r13
movq %r12, %rdi
callq 0x3760
cmpq %r13, %rbx
jne 0x2d8d
movq 0x30(%r14), %rax
cmpq 0x38(%r14), %rax
jne 0x2cc0
movq 0x48(%r14), %rax
movq -0x8(%rax), %rax
movl $0x200, %ecx            # imm = 0x200
addq %rcx, %rax
movq -0x8(%rax), %rbx
movq (%rbx), %rax
movq %rbx, %rdi
movq %r15, %rsi
callq *0x28(%rax)
movq %rax, %r13
movq %r14, %rdi
callq 0x3924
movq 0x30(%r14), %rax
cmpq 0x10(%r14), %rax
je 0x2d5d
cmpq 0x38(%r14), %rax
jne 0x2cfb
movq 0x48(%r14), %rax
movq -0x8(%rax), %rax
movl $0x200, %ecx            # imm = 0x200
addq %rcx, %rax
movq -0x8(%rax), %rdi
movss (%r15), %xmm0
movq (%rdi), %rax
movq %r13, %rsi
callq *0x8(%rax)
jmp 0x2c5c
pushq $0x50
popq %rdi
callq 0x2150
movq %rax, %r14
movq %rax, %rdi
callq 0x45a0
movq -0x38(%rbp), %rax
movq %r14, 0x8(%rax)
leaq -0x90(%rbp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x21d0
movq (%r14), %rax
movq %r14, %rdi
movss -0x2c(%rbp), %xmm0
movq %rbx, %rsi
callq *(%rax)
leaq -0x90(%rbp), %rdi
callq 0x20a0
jmp 0x2da5
pushq $0x40
popq %rdi
callq 0x2150
movq %rax, %r12
movq %rax, %rdi
callq 0x3bec
movss (%r15), %xmm0
movq (%r12), %rax
movq %r12, %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq *0x10(%rax)
movq -0x38(%rbp), %rax
movq %r12, 0x8(%rax)
movq %r15, %rdi
callq 0x2130
movq %r14, %rdi
callq 0x3424
movq %r14, %rdi
callq 0x2130
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
movq %r12, %rdi
jmp 0x2dde
movq %rax, %rbx
leaq -0x90(%rbp), %rdi
jmp 0x2dd1
jmp 0x2dd8
movq %rax, %rbx
leaq -0x70(%rbp), %rdi
callq 0x20a0
jmp 0x2de3
movq %rax, %rbx
movq %r14, %rdi
callq 0x2130
movq %rbx, %rdi
callq 0x2270
nop