// File: cpottamus[P]btree_lab/btree.cc
// Function: BTreeIndex::Rebalance(unsigned int const&, std::vector<unsigned int, std::allocator<unsigned int>>)
ERROR_T BTreeIndex::Rebalance(const SIZE_T &node, std::vector<SIZE_T> ptrPath)
{
  BTreeNode b;
  BTreeNode leftNode;
  BTreeNode rightNode;
  ERROR_T rc;
  SIZE_T offset;
    
  int newType;
  //SIZE_T ptr;
  rc = b.Unserialize(buffercache, node);
  if (rc) { return rc;}
  //std::cout<<":::: Allocating new Nodes :::::"<<std::endl;
  //Allocate 2 new nodes, fill them from the place you're splitting
  SIZE_T leftPtr;
  SIZE_T rightPtr;
  AllocateNode(leftPtr);
  if(b.info.nodetype == BTREE_LEAF_NODE){
    newType = BTREE_LEAF_NODE;
  }else{
    newType = BTREE_INTERIOR_NODE;
  }
  leftNode = BTreeNode(newType, superblock.info.keysize, superblock.info.valuesize, superblock.info.blocksize);
  rc = leftNode.Serialize(buffercache, leftPtr);
  AllocateNode(rightPtr);
  rightNode = BTreeNode(newType, superblock.info.keysize, superblock.info.valuesize, superblock.info.blocksize);
  rc = rightNode.Serialize(buffercache, rightPtr);
  //Unserialize to write to new nodes
  rc = leftNode.Unserialize(buffercache, leftPtr);
  if (rc) { return rc;}
  rc = rightNode.Unserialize(buffercache, rightPtr);
  if (rc) { return rc;}

  //Variables to hold spot/key vals  
  KEY_T keySpot;
  KEY_T testKey;
  VALUE_T valSpot;
  SIZE_T ptrSpot;

  //Find splitting point
  int midpoint = (b.info.numkeys+0.5)/2;

  //If A leafNode
  if(b.info.nodetype==BTREE_LEAF_NODE){
  //Build left leaf node, include the splitting key (this is a <= B+ tree)
    for(offset = 0; (int)offset < midpoint; offset++){
      //std::cout<<":::: OFFSET for building new left leaf node = "<<offset<<std::endl;
      leftNode.info.numkeys++;

    //Get old node values
      rc = b.GetKey(offset, keySpot);
      if (rc) { return rc;}
      rc = b.GetVal(offset, valSpot);
      if (rc) { return rc;}
    //set values in new left node.
      rc = leftNode.SetKey(offset, keySpot);
      if (rc) { return rc;}
      rc = leftNode.SetVal(offset, valSpot);
      if (rc) { return rc;}
    }
  //Build right leaf node
    int spot=0;
    for(offset = midpoint; offset<b.info.numkeys; offset++){
      //std::cout<<":::: OFFSET (spot) for building new right leaf node = "<<spot<<std::endl;
      //std::cout<<":::: Total Block OFFSET (offset), while rebuilding right leaf node"<<offset<<std::endl;
    //Get values from old node.
      rightNode.info.numkeys++;
      rc = b.GetKey(offset, keySpot);
      if (rc) { return rc;}
      rc = b.GetVal(offset, valSpot);
      if (rc) { return rc;}
    //set values in new right node.
      rc = rightNode.SetKey(spot, keySpot);
      if (rc) { return rc;}
      rc = rightNode.SetVal(spot, valSpot);
      if (rc) { return rc;}
      spot++;
    }
  } else {//if it's an interior node.
      //Build left interior node
  for(offset = 0; (int)offset < midpoint; offset++){
    //std::cout<<":::: OFFSET for building new left interior node = "<<offset<<std::endl;
    leftNode.info.numkeys++;
        //Get old key and pointers
    rc = b.GetKey(offset, keySpot);
    if (rc) { return rc;}
    rc = b.GetPtr(offset, ptrSpot);
    if (rc) { return rc;}
        //Set new key and Pointer vals
    rc = leftNode.SetKey(offset, keySpot);
    if (rc) { return rc;}
    rc = leftNode.SetPtr(offset, ptrSpot);
  }
      //Build Right interior node
  int spot=0;
  for(offset = midpoint; offset<b.info.numkeys; offset++){
    //std::cout<<":::: OFFSET (spot) for building new right interior node = "<<spot<<std::endl;
    //std::cout<<":::: Total Block OFFSET (offset), while rebuilding right interior node"<<offset<<std::endl;
    rightNode.info.numkeys++;
    //Get values from old node.
    rc = b.GetKey(offset, keySpot);
    if (rc) { return rc;}
    rc = b.GetPtr(offset, ptrSpot);
    if (rc) { return rc;}
    //set values in new right node.
    rc = rightNode.SetKey(spot, keySpot);
    if (rc) { return rc;}
    rc = rightNode.SetPtr(spot, ptrSpot);
    if (rc) { return rc;}
    spot++;
  }
  rc = b.GetPtr(offset, ptrSpot);
  if (rc) { return rc;}
  rc = rightNode.SetPtr(spot, ptrSpot);
  if (rc) { return rc;}
}
  //Serialize the new nodes
rc = leftNode.Serialize(buffercache, leftPtr);
if (rc) { return rc;}
rc = rightNode.Serialize(buffercache, rightPtr);
if (rc) { return rc;}
rc = b.Serialize(buffercache, node);

  //Find split key
KEY_T splitKey;
rc = b.GetKey(midpoint-1, splitKey);
if (rc) { return rc;}


  //If we're all the way up at the root, we need to make a new root.
  //  std::cout << ":::: NODE TYPE = " << b.info.nodetype << std::endl;
    
  //  std::cout<<"current node nodetype :::: "<<b.info.nodetype<<std::endl;
if (b.info.nodetype == BTREE_ROOT_NODE) {
  //std::cout<<":::: AT THE TOP, BUILDING A NEW ROOT ::::"<<std::endl;
  SIZE_T newRootPtr;
  BTreeNode newRootNode;
  AllocateNode(newRootPtr);
  newRootNode = BTreeNode(BTREE_ROOT_NODE, superblock.info.keysize, superblock.info.valuesize, superblock.info.blocksize);
  superblock.info.rootnode = newRootPtr;
    newRootNode.info.rootnode = newRootPtr;
    newRootNode.info.numkeys = 1;
    newRootNode.SetKey(0, splitKey);
    newRootNode.SetPtr(0, leftPtr);
    newRootNode.SetPtr(1, rightPtr);
  rc = newRootNode.Serialize(buffercache, newRootPtr);
  if(rc) {return rc;}
//std::cout<<"::: We made it here! Root node"<<std::endl;
}
else{
//Find the parent node
  SIZE_T parentPtr = ptrPath.back();
//  std::cout<<"WE BUILT THIS CITY ON ROCK AND ROLL COW ::: "<<parentPtr<<std::endl;
      //std::cout<<"ALSO THIS  IN OUR REBALANCE::: "<<ptrPath.size()<<std::endl;
//    for(int i =ptrPath.size()-1; i>=0; i--) {
//        std::cout<<"Little sumpin"<<ptrPath.at(i)<<std::endl;
//      }
  ptrPath.pop_back();
  BTreeNode parentNode;
  rc = parentNode.Unserialize(buffercache, parentPtr);
  if(rc) {return rc;}

    if (parentNode.info.nodetype == BTREE_SUPERBLOCK) {
        AllocateNode(parentPtr);
        
    }
//Increment the key count for the given node.
  //parentNode.info.numkeys++;
    
    BTreeNode newParentNode = BTreeNode(parentNode.info.nodetype, superblock.info.keysize, superblock.info.valuesize, superblock.info.blocksize);
    newParentNode.info.numkeys = parentNode.info.numkeys + 1;
    newParentNode.info.freelist = parentNode.info.freelist;
    
    bool newKeyInserted = false;
    for (offset = 0; offset < newParentNode.info.numkeys - 1; offset++) {
        rc = parentNode.GetKey(offset, testKey);
        //    if(rc){ return rc;}
        if (newKeyInserted) {
            rc = parentNode.GetKey(offset, keySpot);
            newParentNode.SetKey(offset + 1, keySpot);
            
            rc = parentNode.GetPtr(offset + 1, ptrSpot);
            newParentNode.SetPtr(offset + 2, ptrSpot);
        } else {
            if (splitKey < testKey) {
                newKeyInserted = true;
                newParentNode.SetPtr(offset, leftPtr);
                newParentNode.SetKey(offset, splitKey);
                newParentNode.SetPtr(offset+1, rightPtr);
                offset = offset - 1;
                
            } else {
                rc = parentNode.GetKey(offset, keySpot);
                if (rc) {return rc;}
                rc = newParentNode.SetKey(offset, keySpot);
                if (rc) {return rc;}
                
                rc = parentNode.GetPtr(offset, ptrSpot);
                if (rc) {return rc;}
                rc = newParentNode.SetPtr(offset, ptrSpot);
                if (rc) {return rc;}
            }
        }
    }
    if (newKeyInserted == false) {
        newKeyInserted = true;
        newParentNode.SetPtr(offset, leftPtr);
        newParentNode.SetKey(offset, splitKey);
        newParentNode.SetPtr(offset+1, rightPtr);
    }
    
    newParentNode.Serialize(buffercache, parentPtr);
    
    
//find split keys spot in parent (interior) node, insert it and update keys and pointers.
//  for(offset = 0; offset<parentNode.info.numkeys-1; offset++){
//    //std::cout<<":::: Searching Interior Nodes for splitKey Insertion ::::: offset = "<<offset<<std::endl;
//    rc = parentNode.GetKey(offset, testKey);
//    if(rc){ return rc;}
//    if(splitKey < testKey || splitKey == testKey){ // if testkey > splitkey
//      //std::cout<<":::: Moving through the parent node for rebalance insertion ::: Number of keys in parent = "<<parentNode.info.numkeys<<std::endl;
//      //std::cout<<":::: Moving through the parent node for rebalance insertion ::: parent nodetype = "<<parentNode.info.nodetype<<std::endl;
//          //Once you've found the insertion point for the new key, move all other keys & pointers over by 1
//      for(offset2= parentNode.info.numkeys-2 ; offset2 >= offset; offset2-- ){
//        //std::cout<<":::: Found INSERTION POINT, moving spots over :::: = offset"<<offset<<std::endl;
//            //Grab the old key and pointer
//        rc = parentNode.GetKey(offset2, keySpot);
//        if(rc){ return rc;}
//        rc = parentNode.GetPtr(offset2, ptrSpot);
//        if(rc){ return rc;}
//            //Move it up by 1
//        rc = parentNode.SetKey(offset2+1, keySpot);
//        if(rc){ return rc;}
//        rc = parentNode.SetPtr(offset2+2, ptrSpot);
//      }
//          //We now have moved every pointer over except for the  1 to the immediate right of where we will be inserting our splitKey
//          //Set our pointers and our new key
//      rc = parentNode.SetPtr(offset2+1, rightPtr);
//      if(rc){ return rc;}
//      rc = parentNode.SetPtr(offset,leftPtr);
//      if(rc){ return rc;}
//      rc = parentNode.SetKey(offset, splitKey);
//      if(rc){ return rc;}
//
//      break;
//    }
//  }


  //Check the length of the node and call rebalance if necessary
  //parentNode.Serialize(buffercache, parentPtr);

  if((int)newParentNode.info.numkeys > (int)(2*maxNumKeys/3)){
    rc = Rebalance(parentPtr, ptrPath);
    if(rc){ return rc;}
  }
}
  //Deallocate the old (too large) node
DeallocateNode(node);
return ERROR_NOERROR;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x340, %rsp            # imm = 0x340
movq %rdx, -0x2a0(%rbp)
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x298(%rbp)
leaq -0x48(%rbp), %rdi
callq 0xee80
leaq -0x70(%rbp), %rdi
callq 0xee80
jmp 0xb79d
leaq -0xa8(%rbp), %rdi
callq 0xee80
jmp 0xb7ab
movq -0x298(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x18(%rbp), %rax
movl (%rax), %edx
leaq -0x48(%rbp), %rdi
callq 0xf1a0
movl %eax, -0x2a4(%rbp)
jmp 0xb7cd
movl -0x2a4(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xb82d
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9ef
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0xca2e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0xca25
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0xca19
movq -0x298(%rbp), %rdi
leaq -0xbc(%rbp), %rsi
callq 0x9e90
jmp 0xb842
cmpl $0x4, -0x48(%rbp)
jne 0xb854
movl $0x4, -0xb4(%rbp)
jmp 0xb85e
movl $0x3, -0xb4(%rbp)
movq -0x298(%rbp), %rax
movl -0xb4(%rbp), %esi
movl 0x1c(%rax), %edx
movl 0x20(%rax), %ecx
movl 0x24(%rax), %r8d
leaq -0xe8(%rbp), %rdi
callq 0xeef0
jmp 0xb883
leaq -0x70(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
callq 0xf050
jmp 0xb895
leaq -0xe8(%rbp), %rdi
callq 0xeea0
movq -0x298(%rbp), %rax
movq 0x8(%rax), %rsi
movl -0xbc(%rbp), %edx
leaq -0x70(%rbp), %rdi
callq 0xf080
movl %eax, -0x2a8(%rbp)
jmp 0xb8c3
movq -0x298(%rbp), %rdi
movl -0x2a8(%rbp), %eax
movl %eax, -0xac(%rbp)
leaq -0xc0(%rbp), %rsi
callq 0x9e90
jmp 0xb8e4
movq -0x298(%rbp), %rax
movl -0xb4(%rbp), %esi
movl 0x1c(%rax), %edx
movl 0x20(%rax), %ecx
movl 0x24(%rax), %r8d
leaq -0x110(%rbp), %rdi
callq 0xeef0
jmp 0xb909
leaq -0xa8(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0xf050
jmp 0xb91e
leaq -0x110(%rbp), %rdi
callq 0xeea0
movq -0x298(%rbp), %rax
movq 0x8(%rax), %rsi
movl -0xc0(%rbp), %edx
leaq -0xa8(%rbp), %rdi
callq 0xf080
movl %eax, -0x2ac(%rbp)
jmp 0xb94f
movq -0x298(%rbp), %rax
movl -0x2ac(%rbp), %ecx
movl %ecx, -0xac(%rbp)
movq 0x8(%rax), %rsi
movl -0xbc(%rbp), %edx
leaq -0x70(%rbp), %rdi
callq 0xf1a0
movl %eax, -0x2b0(%rbp)
jmp 0xb97d
movl -0x2b0(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xb9e4
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9ef
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0xeea0
jmp 0xca19
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x110(%rbp), %rdi
callq 0xeea0
jmp 0xca19
movq -0x298(%rbp), %rax
movq 0x8(%rax), %rsi
movl -0xc0(%rbp), %edx
leaq -0xa8(%rbp), %rdi
callq 0xf1a0
movl %eax, -0x2b4(%rbp)
jmp 0xba09
movl -0x2b4(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xba36
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9ef
leaq -0x138(%rbp), %rdi
callq 0x43e0
jmp 0xba44
leaq -0x160(%rbp), %rdi
callq 0x43e0
jmp 0xba52
leaq -0x188(%rbp), %rdi
callq 0x43e0
jmp 0xba60
movl -0x30(%rbp), %eax
cvtsi2sd %rax, %xmm0
movsd 0x47b0(%rip), %xmm1     # 0x10220
addsd %xmm1, %xmm0
movsd 0x4c1c(%rip), %xmm1     # 0x10698
divsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x190(%rbp)
cmpl $0x4, -0x48(%rbp)
jne 0xbdba
movl $0x0, -0xb0(%rbp)
movl -0xb0(%rbp), %eax
cmpl -0x190(%rbp), %eax
jge 0xbc2d
movl -0x58(%rbp), %eax
incl %eax
movl %eax, -0x58(%rbp)
movl -0xb0(%rbp), %esi
leaq -0x48(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf5d0
movl %eax, -0x2b8(%rbp)
jmp 0xbad6
movl -0x2b8(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbb36
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0xc9e1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0xc9d5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0xc9c9
movl -0xb0(%rbp), %esi
leaq -0x48(%rbp), %rdi
leaq -0x188(%rbp), %rdx
callq 0xf6a0
movl %eax, -0x2bc(%rbp)
jmp 0xbb54
movl -0x2bc(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbb81
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0xb0(%rbp), %esi
leaq -0x70(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf780
movl %eax, -0x2c0(%rbp)
jmp 0xbb9f
movl -0x2c0(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbbcc
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0xb0(%rbp), %esi
leaq -0x70(%rbp), %rdi
leaq -0x188(%rbp), %rdx
callq 0xf840
movl %eax, -0x2c4(%rbp)
jmp 0xbbea
movl -0x2c4(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbc17
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
jmp 0xbc19
movl -0xb0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb0(%rbp)
jmp 0xba9e
movl $0x0, -0x194(%rbp)
movl -0x190(%rbp), %eax
movl %eax, -0xb0(%rbp)
movl -0xb0(%rbp), %eax
cmpl -0x30(%rbp), %eax
jae 0xbdb5
movl -0x90(%rbp), %eax
incl %eax
movl %eax, -0x90(%rbp)
movl -0xb0(%rbp), %esi
leaq -0x48(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf5d0
movl %eax, -0x2c8(%rbp)
jmp 0xbc7e
movl -0x2c8(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbcab
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0xb0(%rbp), %esi
leaq -0x48(%rbp), %rdi
leaq -0x188(%rbp), %rdx
callq 0xf6a0
movl %eax, -0x2cc(%rbp)
jmp 0xbcc9
movl -0x2cc(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbcf6
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0x194(%rbp), %esi
leaq -0xa8(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf780
movl %eax, -0x2d0(%rbp)
jmp 0xbd17
movl -0x2d0(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbd44
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0x194(%rbp), %esi
leaq -0xa8(%rbp), %rdi
leaq -0x188(%rbp), %rdx
callq 0xf840
movl %eax, -0x2d4(%rbp)
jmp 0xbd65
movl -0x2d4(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbd92
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0x194(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x194(%rbp)
movl -0xb0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb0(%rbp)
jmp 0xbc43
jmp 0xc120
movl $0x0, -0xb0(%rbp)
movl -0xb0(%rbp), %eax
cmpl -0x190(%rbp), %eax
jge 0xbefd
movl -0x58(%rbp), %eax
incl %eax
movl %eax, -0x58(%rbp)
movl -0xb0(%rbp), %esi
leaq -0x48(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf5d0
movl %eax, -0x2d8(%rbp)
jmp 0xbdfc
movl -0x2d8(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbe29
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0xb0(%rbp), %esi
leaq -0x48(%rbp), %rdi
leaq -0x18c(%rbp), %rdx
callq 0xf650
movl %eax, -0x2dc(%rbp)
jmp 0xbe47
movl -0x2dc(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbe74
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0xb0(%rbp), %esi
leaq -0x70(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf780
movl %eax, -0x2e0(%rbp)
jmp 0xbe92
movl -0x2e0(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbebf
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0xb0(%rbp), %esi
leaq -0x70(%rbp), %rdi
leaq -0x18c(%rbp), %rdx
callq 0xf7f0
movl %eax, -0x2e4(%rbp)
jmp 0xbedd
movl -0x2e4(%rbp), %eax
movl %eax, -0xac(%rbp)
movl -0xb0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb0(%rbp)
jmp 0xbdc4
movl $0x0, -0x198(%rbp)
movl -0x190(%rbp), %eax
movl %eax, -0xb0(%rbp)
movl -0xb0(%rbp), %eax
cmpl -0x30(%rbp), %eax
jae 0xc085
movl -0x90(%rbp), %eax
incl %eax
movl %eax, -0x90(%rbp)
movl -0xb0(%rbp), %esi
leaq -0x48(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf5d0
movl %eax, -0x2e8(%rbp)
jmp 0xbf4e
movl -0x2e8(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbf7b
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0xb0(%rbp), %esi
leaq -0x48(%rbp), %rdi
leaq -0x18c(%rbp), %rdx
callq 0xf650
movl %eax, -0x2ec(%rbp)
jmp 0xbf99
movl -0x2ec(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xbfc6
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0x198(%rbp), %esi
leaq -0xa8(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf780
movl %eax, -0x2f0(%rbp)
jmp 0xbfe7
movl -0x2f0(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc014
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0x198(%rbp), %esi
leaq -0xa8(%rbp), %rdi
leaq -0x18c(%rbp), %rdx
callq 0xf7f0
movl %eax, -0x2f4(%rbp)
jmp 0xc035
movl -0x2f4(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc062
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0x198(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x198(%rbp)
movl -0xb0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb0(%rbp)
jmp 0xbf13
movl -0xb0(%rbp), %esi
leaq -0x48(%rbp), %rdi
leaq -0x18c(%rbp), %rdx
callq 0xf650
movl %eax, -0x2f8(%rbp)
jmp 0xc0a3
movl -0x2f8(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc0d0
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movl -0x198(%rbp), %esi
leaq -0xa8(%rbp), %rdi
leaq -0x18c(%rbp), %rdx
callq 0xf7f0
movl %eax, -0x2fc(%rbp)
jmp 0xc0f1
movl -0x2fc(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc11e
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
jmp 0xc120
movq -0x298(%rbp), %rax
movq 0x8(%rax), %rsi
movl -0xbc(%rbp), %edx
leaq -0x70(%rbp), %rdi
callq 0xf080
movl %eax, -0x300(%rbp)
jmp 0xc142
movl -0x300(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc16f
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movq -0x298(%rbp), %rax
movq 0x8(%rax), %rsi
movl -0xc0(%rbp), %edx
leaq -0xa8(%rbp), %rdi
callq 0xf080
movl %eax, -0x304(%rbp)
jmp 0xc194
movl -0x304(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc1c1
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc9a3
movq -0x298(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x18(%rbp), %rax
movl (%rax), %edx
leaq -0x48(%rbp), %rdi
callq 0xf080
movl %eax, -0x308(%rbp)
jmp 0xc1e3
movl -0x308(%rbp), %eax
movl %eax, -0xac(%rbp)
leaq -0x1c0(%rbp), %rdi
callq 0x43e0
jmp 0xc1fd
movl -0x190(%rbp), %esi
decl %esi
leaq -0x48(%rbp), %rdi
leaq -0x1c0(%rbp), %rdx
callq 0xf5d0
movl %eax, -0x30c(%rbp)
jmp 0xc21d
movl -0x30c(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc25b
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc987
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0xc995
cmpl $0x2, -0x48(%rbp)
jne 0xc3ee
leaq -0x1f0(%rbp), %rdi
callq 0xee80
jmp 0xc273
movq -0x298(%rbp), %rdi
leaq -0x1c4(%rbp), %rsi
callq 0x9e90
jmp 0xc288
movq -0x298(%rbp), %rax
movl 0x1c(%rax), %edx
movl 0x20(%rax), %ecx
movl 0x24(%rax), %r8d
leaq -0x218(%rbp), %rdi
movl $0x2, %esi
callq 0xeef0
jmp 0xc2ac
leaq -0x1f0(%rbp), %rdi
leaq -0x218(%rbp), %rsi
callq 0xf050
jmp 0xc2c1
leaq -0x218(%rbp), %rdi
callq 0xeea0
movq -0x298(%rbp), %rax
movl -0x1c4(%rbp), %ecx
movl %ecx, 0x28(%rax)
movl -0x1c4(%rbp), %eax
movl %eax, -0x1e0(%rbp)
movl $0x1, -0x1d8(%rbp)
leaq -0x1f0(%rbp), %rdi
xorl %esi, %esi
leaq -0x1c0(%rbp), %rdx
callq 0xf780
jmp 0xc30a
leaq -0x1f0(%rbp), %rdi
xorl %esi, %esi
leaq -0xbc(%rbp), %rdx
callq 0xf7f0
jmp 0xc321
leaq -0x1f0(%rbp), %rdi
movl $0x1, %esi
leaq -0xc0(%rbp), %rdx
callq 0xf7f0
jmp 0xc33b
movq -0x298(%rbp), %rax
movq 0x8(%rax), %rsi
movl -0x1c4(%rbp), %edx
leaq -0x1f0(%rbp), %rdi
callq 0xf080
movl %eax, -0x310(%rbp)
jmp 0xc360
movl -0x310(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc3b2
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc3bc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0xc3dd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x218(%rbp), %rdi
callq 0xeea0
jmp 0xc3dd
movl $0x0, -0xb8(%rbp)
leaq -0x1f0(%rbp), %rdi
callq 0xeea0
movl -0xb8(%rbp), %eax
testl %eax, %eax
jne 0xc987
jmp 0xc3d8
jmp 0xc964
leaq -0x1f0(%rbp), %rdi
callq 0xeea0
jmp 0xc995
movq -0x2a0(%rbp), %rdi
callq 0xdc00
movq -0x2a0(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x21c(%rbp)
callq 0xdc40
leaq -0x248(%rbp), %rdi
callq 0xee80
jmp 0xc41c
movq -0x298(%rbp), %rax
movq 0x8(%rax), %rsi
movl -0x21c(%rbp), %edx
leaq -0x248(%rbp), %rdi
callq 0xf1a0
movl %eax, -0x314(%rbp)
jmp 0xc441
movl -0x314(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc47f
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc930
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0xc956
cmpl $0x1, -0x248(%rbp)
jne 0xc49f
movq -0x298(%rbp), %rdi
leaq -0x21c(%rbp), %rsi
callq 0x9e90
jmp 0xc49d
jmp 0xc49f
movq -0x298(%rbp), %rax
movl -0x248(%rbp), %esi
movl 0x1c(%rax), %edx
movl 0x20(%rax), %ecx
movl 0x24(%rax), %r8d
leaq -0x270(%rbp), %rdi
callq 0xeef0
jmp 0xc4c4
movl -0x230(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x258(%rbp)
movl -0x234(%rbp), %eax
movl %eax, -0x25c(%rbp)
movb $0x0, -0x271(%rbp)
movl $0x0, -0xb0(%rbp)
movl -0xb0(%rbp), %eax
movl -0x258(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jae 0xc7d5
movl -0xb0(%rbp), %esi
leaq -0x248(%rbp), %rdi
leaq -0x160(%rbp), %rdx
callq 0xf5d0
movl %eax, -0x318(%rbp)
jmp 0xc528
movl -0x318(%rbp), %eax
movl %eax, -0xac(%rbp)
testb $0x1, -0x271(%rbp)
je 0xc5ee
movl -0xb0(%rbp), %esi
leaq -0x248(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf5d0
movl %eax, -0x31c(%rbp)
jmp 0xc562
movl -0x31c(%rbp), %eax
movl %eax, -0xac(%rbp)
movl -0xb0(%rbp), %esi
incl %esi
leaq -0x270(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf780
jmp 0xc58b
movl -0xb0(%rbp), %esi
incl %esi
leaq -0x248(%rbp), %rdi
leaq -0x18c(%rbp), %rdx
callq 0xf650
movl %eax, -0x320(%rbp)
jmp 0xc5ae
movl -0x320(%rbp), %eax
movl %eax, -0xac(%rbp)
movl -0xb0(%rbp), %esi
addl $0x2, %esi
leaq -0x270(%rbp), %rdi
leaq -0x18c(%rbp), %rdx
callq 0xf7f0
jmp 0xc5d8
jmp 0xc7bf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0xc94a
leaq -0x1c0(%rbp), %rdi
leaq -0x160(%rbp), %rsi
callq 0x47c0
movb %al, -0x321(%rbp)
jmp 0xc609
movb -0x321(%rbp), %al
testb $0x1, %al
jne 0xc615
jmp 0xc683
movb $0x1, -0x271(%rbp)
movl -0xb0(%rbp), %esi
leaq -0x270(%rbp), %rdi
leaq -0xbc(%rbp), %rdx
callq 0xf7f0
jmp 0xc637
movl -0xb0(%rbp), %esi
leaq -0x270(%rbp), %rdi
leaq -0x1c0(%rbp), %rdx
callq 0xf780
jmp 0xc652
movl -0xb0(%rbp), %esi
incl %esi
leaq -0x270(%rbp), %rdi
leaq -0xc0(%rbp), %rdx
callq 0xf7f0
jmp 0xc66f
movl -0xb0(%rbp), %eax
subl $0x1, %eax
movl %eax, -0xb0(%rbp)
jmp 0xc7bd
movl -0xb0(%rbp), %esi
leaq -0x248(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf5d0
movl %eax, -0x328(%rbp)
jmp 0xc6a4
movl -0x328(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc6d1
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc924
movl -0xb0(%rbp), %esi
leaq -0x270(%rbp), %rdi
leaq -0x138(%rbp), %rdx
callq 0xf780
movl %eax, -0x32c(%rbp)
jmp 0xc6f2
movl -0x32c(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc71f
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc924
movl -0xb0(%rbp), %esi
leaq -0x248(%rbp), %rdi
leaq -0x18c(%rbp), %rdx
callq 0xf650
movl %eax, -0x330(%rbp)
jmp 0xc740
movl -0x330(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc76d
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc924
movl -0xb0(%rbp), %esi
leaq -0x270(%rbp), %rdi
leaq -0x18c(%rbp), %rdx
callq 0xf7f0
movl %eax, -0x334(%rbp)
jmp 0xc78e
movl -0x334(%rbp), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0xc7bb
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc924
jmp 0xc7bd
jmp 0xc7bf
jmp 0xc7c1
movl -0xb0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb0(%rbp)
jmp 0xc4f0
movb -0x271(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0xc841
movb $0x1, -0x271(%rbp)
movl -0xb0(%rbp), %esi
leaq -0x270(%rbp), %rdi
leaq -0xbc(%rbp), %rdx
callq 0xf7f0
jmp 0xc807
movl -0xb0(%rbp), %esi
leaq -0x270(%rbp), %rdi
leaq -0x1c0(%rbp), %rdx
callq 0xf780
jmp 0xc822
movl -0xb0(%rbp), %esi
incl %esi
leaq -0x270(%rbp), %rdi
leaq -0xc0(%rbp), %rdx
callq 0xf7f0
jmp 0xc83f
jmp 0xc841
movq -0x298(%rbp), %rax
movq 0x8(%rax), %rsi
movl -0x21c(%rbp), %edx
leaq -0x270(%rbp), %rdi
callq 0xf080
jmp 0xc860
movq -0x298(%rbp), %rax
movl -0x258(%rbp), %ecx
movl %ecx, -0x338(%rbp)
movl 0x40(%rax), %eax
shll %eax
movl $0x3, %ecx
xorl %edx, %edx
divl %ecx
movl %eax, %ecx
movl -0x338(%rbp), %eax
cmpl %ecx, %eax
jle 0xc91a
movq -0x2a0(%rbp), %rsi
leaq -0x290(%rbp), %rdi
callq 0xdc70
jmp 0xc8a6
movq -0x298(%rbp), %rdi
leaq -0x21c(%rbp), %rsi
leaq -0x290(%rbp), %rdx
callq 0xb760
movl %eax, -0x33c(%rbp)
jmp 0xc8c8
movl -0x33c(%rbp), %eax
movl %eax, -0xac(%rbp)
leaq -0x290(%rbp), %rdi
callq 0xdd60
cmpl $0x0, -0xac(%rbp)
je 0xc918
movl -0xac(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0xc924
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x290(%rbp), %rdi
callq 0xdd60
jmp 0xc94a
jmp 0xc91a
movl $0x0, -0xb8(%rbp)
leaq -0x270(%rbp), %rdi
callq 0xeea0
leaq -0x248(%rbp), %rdi
callq 0xeea0
movl -0xb8(%rbp), %eax
testl %eax, %eax
jne 0xc987
jmp 0xc948
jmp 0xc964
leaq -0x270(%rbp), %rdi
callq 0xeea0
leaq -0x248(%rbp), %rdi
callq 0xeea0
jmp 0xc995
movq -0x298(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x9f80
jmp 0xc976
movl $0x0, -0x4(%rbp)
movl $0x1, -0xb8(%rbp)
leaq -0x1c0(%rbp), %rdi
callq 0x46e0
jmp 0xc9a3
leaq -0x1c0(%rbp), %rdi
callq 0x46e0
jmp 0xc9c9
leaq -0x188(%rbp), %rdi
callq 0x46e0
leaq -0x160(%rbp), %rdi
callq 0x46e0
leaq -0x138(%rbp), %rdi
callq 0x46e0
jmp 0xc9ef
leaq -0x188(%rbp), %rdi
callq 0x46e0
leaq -0x160(%rbp), %rdi
callq 0x46e0
leaq -0x138(%rbp), %rdi
callq 0x46e0
jmp 0xca19
leaq -0xa8(%rbp), %rdi
callq 0xeea0
leaq -0x70(%rbp), %rdi
callq 0xeea0
leaq -0x48(%rbp), %rdi
callq 0xeea0
movl -0x4(%rbp), %eax
addq $0x340, %rsp            # imm = 0x340
popq %rbp
retq
leaq -0xa8(%rbp), %rdi
callq 0xeea0
leaq -0x70(%rbp), %rdi
callq 0xeea0
leaq -0x48(%rbp), %rdi
callq 0xeea0
movq -0x78(%rbp), %rdi
callq 0x3400