// File: /workspace/github_cpp_makefile_star2_O1/GAStudyGroup[P]GPX2/src/cross/gpx/sources/GPX2Fusion.cpp
// Function: GPX2Fusion::fusePartitions(std::vector<GPX2Structs::UnfeasibleConnection, std::allocator<GPX2Structs::UnfeasibleConnection>>&, std::map<int, Partition*, std::less<int>, std::allocator<std::pair<int const, Partition*>>>&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, Node*, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, Node*>>>&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, Node*, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, Node*>>>&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, Node*, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, Node*>>>&)
void GPX2Fusion::fusePartitions(vector<GPX2Structs::UnfeasibleConnection> &fuseWith,GPX2Structs::PartitionMap &partitions, GPX2Structs::NodeMap &unitedGraph, GPX2Structs::NodeMap& red, GPX2Structs::NodeMap& blue)
{ // Realiza a fusão entre as partições, de acordo com as validações já realizadas
    // Início da execução da fusão em si
    for (auto it = fuseWith.begin(); it != fuseWith.end();) {
        // Não precisa mudar o custo pois a checkPartition não verifica isso
        Partition* p1Ptr = partitions[(*it).partitionId1];
        Partition* p2Ptr = partitions[(*it).partitionId2];
        vector<string> intermediariesNodes, accessNodesToRemove;

        // Deletar as entradas de conexões (connectTo) diferentes da partição que será fundida
        for (auto itIn = p1Ptr->getConnectedTo().begin(); itIn != p1Ptr->getConnectedTo().end();) {
            if ((*itIn).connectedPartition != (*it).partitionId2) {
                p1Ptr->getConnectedTo().erase(itIn);
            } else {
                itIn++;
            }
        }
        for (auto itIn = p2Ptr->getConnectedTo().begin(); itIn != p2Ptr->getConnectedTo().end();) {
            if ((*itIn).connectedPartition != (*it).partitionId1) {
                p2Ptr->getConnectedTo().erase(itIn);
            } else {
                itIn++;
            }
        }

        for (string nodes : p2Ptr->getNodes()) {
            p1Ptr->getNodes().push_back(nodes);
        }
        for (string access : p2Ptr->getAccessNodes()) {
            p1Ptr->getAccessNodes().push_back(access);
        }

        // Percorrer os nós com ligação na partição que será feita a fusão
        for (auto connectedNode : p2Ptr->getConnectedTo()) {

            // Pegar os nós intermediários (o "caminho" da conexão)
            pair<GPX2Structs::SearchResult, vector<string>> tmp = GPX2Support::DFS_outside(connectedNode.node, partitions,unitedGraph);

            // Apagar os access nodes da lista da partição
            accessNodesToRemove.push_back(connectedNode.node);
            accessNodesToRemove.push_back(connectedNode.connectedNode);

            // Apagar o primeiro pois é o nó access que da origem a busca
            if (!tmp.second.empty()) {
                tmp.second.erase(tmp.second.begin());

                // Apagar o último nó pois é onde ele se conecta na partição que será unida
                if (!tmp.second.empty()) {
                    tmp.second.erase(tmp.second.end());
                }
            }

            // Carrega os nós intermediarios
            intermediariesNodes.insert(intermediariesNodes.end(), tmp.second.begin(), tmp.second.end());
        }

        /*  
            Inserir os nós intermediários na nova partição fundida
            Os nós são a ligação entre a P1 e P2, sendo a conexão de fusão das duas
        */
        p1Ptr->getNodes().insert(p1Ptr->getNodes().end(), intermediariesNodes.begin(), intermediariesNodes.end());

        // Os access nodes que ligavam as duas partições não serão mais access nodes, eles serão removidos
        GPX2Support::eraseSubVector(p1Ptr->getAccessNodes(), accessNodesToRemove);

        //atualizar a lista de entradas e saídas
        p1Ptr->setEntryAndExits(GPX2Support::getEntryAndExitList(p1Ptr,red,blue));

        // Apagar tudo
        delete p2Ptr;
        partitions.erase((*it).partitionId2);

        //apaga a entrada na fuseWith pois a fusão já foi realizada
        it = fuseWith.erase(it);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x118, %rsp            # imm = 0x118
movq %r8, 0xf0(%rsp)
movq %rcx, 0xe8(%rsp)
movq %rdx, 0xf8(%rsp)
movq %rsi, (%rsp)
movq (%rdi), %rbx
cmpq 0x8(%rdi), %rbx
je 0x24351
leaq 0x4(%rbx), %rax
movq %rax, 0x50(%rsp)
leaq 0x8(%rsp), %r13
movq %rdi, 0xe0(%rsp)
movq %rbx, 0x58(%rsp)
movq (%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x25076
movq (%rax), %rbx
movq %r14, %rdi
movq 0x50(%rsp), %rsi
callq 0x25076
movq (%rax), %r14
xorl %eax, %eax
movq %rax, 0x90(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
movq %rax, 0xd0(%rsp)
movaps %xmm0, 0xc0(%rsp)
movq %rbx, %rdi
callq 0x2a6e4
movq (%rax), %r12
movq %rbx, %rdi
callq 0x2a6e4
cmpq 0x8(%rax), %r12
je 0x23f8d
movl (%r12), %eax
movq 0x50(%rsp), %rcx
cmpl (%rcx), %eax
je 0x23f87
movq %rbx, %rdi
callq 0x2a6e4
movq %rax, %rdi
movq %r12, %rsi
callq 0x25b58
jmp 0x23f57
addq $0x48, %r12
jmp 0x23f57
movq %r14, %rdi
callq 0x2a6e4
movq (%rax), %r12
movq %r14, %rdi
callq 0x2a6e4
cmpq 0x8(%rax), %r12
je 0x23fce
movl (%r12), %eax
movq 0x58(%rsp), %rcx
cmpl (%rcx), %eax
je 0x23fc8
movq %r14, %rdi
callq 0x2a6e4
movq %rax, %rdi
movq %r12, %rsi
callq 0x25b58
jmp 0x23f98
addq $0x48, %r12
jmp 0x23f98
movq %r14, %rdi
callq 0x2a6bc
movq (%rax), %r12
movq 0x8(%rax), %rbp
cmpq %rbp, %r12
je 0x24035
leaq 0x18(%rsp), %rax
movq %rax, 0x8(%rsp)
movq (%r12), %rsi
movq 0x8(%r12), %rdx
addq %rsi, %rdx
movq %r13, %rdi
callq 0x82cc
movq %rbx, %rdi
callq 0x2a6bc
movq %rax, %rdi
movq %r13, %rsi
callq 0x1a992
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x2402f
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x53c0
addq $0x20, %r12
jmp 0x23fdd
movq %r14, %rdi
callq 0x2a6c2
movq (%rax), %r12
movq 0x8(%rax), %rbp
cmpq %rbp, %r12
je 0x2409c
leaq 0x18(%rsp), %rax
movq %rax, 0x8(%rsp)
movq (%r12), %rsi
movq 0x8(%r12), %rdx
addq %rsi, %rdx
movq %r13, %rdi
callq 0x82cc
movq %rbx, %rdi
callq 0x2a6c2
movq %rax, %rdi
movq %r13, %rsi
callq 0x1a992
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x24096
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x53c0
addq $0x20, %r12
jmp 0x24044
movq %r14, %rdi
callq 0x2a6e4
movq (%rax), %r12
movq 0x8(%rax), %rbp
cmpq %rbp, %r12
je 0x24221
movl (%r12), %eax
movl %eax, 0x8(%rsp)
leaq 0x20(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x8(%r12), %rsi
movq 0x10(%r12), %rdx
addq %rsi, %rdx
leaq 0x10(%rsp), %rdi
callq 0x82cc
leaq 0x40(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x28(%r12), %rsi
movq 0x30(%r12), %rdx
addq %rsi, %rdx
leaq 0x30(%rsp), %rdi
callq 0x82cc
leaq 0xb0(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
addq %rsi, %rdx
leaq 0xa0(%rsp), %r15
movq %r15, %rdi
callq 0x82cc
leaq 0x60(%rsp), %rdi
movq %r15, %rsi
movq (%rsp), %rdx
movq 0xf8(%rsp), %rcx
callq 0x2c0bb
movq 0xa0(%rsp), %rdi
leaq 0xb0(%rsp), %rax
cmpq %rax, %rdi
je 0x24169
movq 0xb0(%rsp), %rsi
incq %rsi
callq 0x53c0
leaq 0xc0(%rsp), %r15
movq %r15, %rdi
leaq 0x10(%rsp), %rsi
callq 0x1a992
movq %r15, %rdi
leaq 0x30(%rsp), %rsi
callq 0x1a992
movq 0x68(%rsp), %rsi
cmpq 0x70(%rsp), %rsi
je 0x241b7
leaq 0x68(%rsp), %rdi
callq 0x25c34
movq 0x70(%rsp), %rsi
cmpq %rsi, 0x68(%rsp)
je 0x241b7
leaq 0x68(%rsp), %rdi
callq 0x25c34
movq 0x88(%rsp), %rsi
movq 0x68(%rsp), %rdx
movq 0x70(%rsp), %rcx
leaq 0x80(%rsp), %rdi
callq 0x25cac
leaq 0x68(%rsp), %rdi
callq 0x81e0
movq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rax
cmpq %rax, %rdi
je 0x241fc
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x53c0
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x24218
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x53c0
addq $0x48, %r12
jmp 0x240ab
movq %rbx, %rdi
callq 0x2a6bc
movq 0xe0(%rsp), %rbp
movq %rax, %r12
movq %rbx, %rdi
callq 0x2a6bc
movq 0x8(%rax), %rsi
movq 0x80(%rsp), %rdx
movq 0x88(%rsp), %rcx
movq %r12, %rdi
callq 0x25cac
movq %rbx, %rdi
callq 0x2a6c2
movq %rax, %rdi
leaq 0xc0(%rsp), %rsi
callq 0x2bb15
leaq 0x100(%rsp), %rdi
movq %rbx, %rsi
movq 0xe8(%rsp), %rdx
movq 0xf0(%rsp), %rcx
callq 0x2caf5
movq %rbx, %rdi
leaq 0x100(%rsp), %rbx
movq %rbx, %rsi
callq 0x2a716
movq %rbx, %rdi
callq 0x181e0
movq 0x68(%r14), %rdi
testq %rdi, %rdi
je 0x242c0
movq 0x78(%r14), %rsi
subq %rdi, %rsi
callq 0x53c0
leaq 0x50(%r14), %rdi
callq 0x251fa
leaq 0x38(%r14), %rdi
callq 0x181e0
leaq 0x20(%r14), %rdi
callq 0x81e0
leaq 0x8(%r14), %rdi
callq 0x81e0
movl $0x80, %esi
movq %r14, %rdi
callq 0x53c0
movq (%rsp), %rdi
movq 0x50(%rsp), %rsi
callq 0x26104
movq (%rsp), %rdi
movq %rax, %rsi
callq 0x2617c
movq 0x58(%rsp), %rbx
leaq 0xc(%rbx), %rsi
movq 0x8(%rbp), %rdx
cmpq %rdx, %rsi
je 0x24328
subq %rsi, %rdx
movq %rbx, %rdi
callq 0x55e0
addq $-0xc, 0x8(%rbp)
leaq 0xc0(%rsp), %rdi
callq 0x81e0
leaq 0x80(%rsp), %rdi
callq 0x81e0
cmpq 0x8(%rbp), %rbx
jne 0x23f05
addq $0x118, %rsp            # imm = 0x118
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0x100(%rsp), %rdi
callq 0x181e0
jmp 0x24438
jmp 0x24435
jmp 0x24435
jmp 0x24435
jmp 0x24435
jmp 0x24435
jmp 0x24435
jmp 0x24435
jmp 0x243f7
jmp 0x243f7
movq %rax, %rbx
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x24438
movq 0x20(%rsp), %rsi
jmp 0x24429
movq %rax, %rbx
jmp 0x24404
jmp 0x243f7
movq %rax, %rbx
movq 0xa0(%rsp), %rdi
leaq 0xb0(%rsp), %rax
cmpq %rax, %rdi
je 0x24404
movq 0xb0(%rsp), %rsi
incq %rsi
callq 0x53c0
jmp 0x24404
jmp 0x24435
jmp 0x24435
jmp 0x24435
jmp 0x24435
jmp 0x24435
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x81e0
leaq 0x8(%rsp), %rdi
callq 0x2503e
jmp 0x24438
jmp 0x24412
movq %rax, %rbx
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x24438
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x53c0
jmp 0x24438
jmp 0x24435
movq %rax, %rbx
leaq 0xc0(%rsp), %rdi
callq 0x81e0
leaq 0x80(%rsp), %rdi
callq 0x81e0
movq %rbx, %rdi
callq 0x5670