// File: /workspace/github_cpp_makefile_star2_O3/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), %r15
cmpq 0x8(%rdi), %r15
je 0x244f1
leaq 0x4(%r15), %rax
movq %rax, 0x50(%rsp)
leaq 0x8(%rsp), %rbp
movq %rdi, 0xe0(%rsp)
movq %r15, 0x58(%rsp)
movq (%rsp), %r14
movq %r14, %rdi
movq %r15, %rsi
callq 0x2524c
movq (%rax), %r12
movq %r14, %rdi
movq 0x50(%rsp), %rsi
callq 0x2524c
movq (%rax), %r15
xorl %eax, %eax
movq %rax, 0x90(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
movq %rax, 0xb0(%rsp)
movaps %xmm0, 0xa0(%rsp)
movq %r12, %rdi
callq 0x2a8f8
movq (%rax), %r13
movq 0x58(%rsp), %r14
movq %r12, %rdi
callq 0x2a8f8
cmpq 0x8(%rax), %r13
je 0x24126
movl (%r13), %eax
movq 0x50(%rsp), %rcx
cmpl (%rcx), %eax
je 0x24120
movq %r12, %rdi
callq 0x2a8f8
movq %rax, %rdi
movq %r13, %rsi
callq 0x25d36
jmp 0x240f0
addq $0x48, %r13
jmp 0x240f0
movq %r15, %rdi
callq 0x2a8f8
movq (%rax), %r13
movq %r15, %rdi
callq 0x2a8f8
cmpq 0x8(%rax), %r13
je 0x24163
movl (%r13), %eax
cmpl (%r14), %eax
je 0x2415d
movq %r15, %rdi
callq 0x2a8f8
movq %rax, %rdi
movq %r13, %rsi
callq 0x25d36
jmp 0x24131
addq $0x48, %r13
jmp 0x24131
movq %r15, %rdi
callq 0x2a8d0
movq (%rax), %r14
movq 0x8(%rax), %r13
cmpq %r13, %r14
je 0x241c8
leaq 0x18(%rsp), %rax
movq %rax, 0x8(%rsp)
movq (%r14), %rsi
movq 0x8(%r14), %rdx
addq %rsi, %rdx
movq %rbp, %rdi
callq 0x82fa
movq %r12, %rdi
callq 0x2a8d0
movq %rax, %rdi
movq %rbp, %rsi
callq 0x1aa0a
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x241c2
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x53b0
addq $0x20, %r14
jmp 0x24172
movq %r15, %rdi
callq 0x2a8d6
movq (%rax), %r14
movq 0x8(%rax), %r13
cmpq %r13, %r14
je 0x2422d
leaq 0x18(%rsp), %rax
movq %rax, 0x8(%rsp)
movq (%r14), %rsi
movq 0x8(%r14), %rdx
addq %rsi, %rdx
movq %rbp, %rdi
callq 0x82fa
movq %r12, %rdi
callq 0x2a8d6
movq %rax, %rdi
movq %rbp, %rsi
callq 0x1aa0a
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x24227
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x53b0
addq $0x20, %r14
jmp 0x241d7
movq %r15, %rdi
callq 0x2a8f8
movq (%rax), %r13
movq 0x8(%rax), %r14
cmpq %r14, %r13
je 0x243ba
movl (%r13), %eax
movl %eax, 0x8(%rsp)
leaq 0x20(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x8(%r13), %rsi
movq 0x10(%r13), %rdx
addq %rsi, %rdx
leaq 0x10(%rsp), %rdi
callq 0x82fa
leaq 0x40(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x28(%r13), %rsi
movq 0x30(%r13), %rdx
addq %rsi, %rdx
leaq 0x30(%rsp), %rdi
callq 0x82fa
leaq 0xd0(%rsp), %rax
movq %rax, 0xc0(%rsp)
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
addq %rsi, %rdx
leaq 0xc0(%rsp), %rbx
movq %rbx, %rdi
callq 0x82fa
leaq 0x60(%rsp), %rdi
movq %rbx, %rsi
movq (%rsp), %rdx
movq 0xf8(%rsp), %rcx
callq 0x2c2d0
movq 0xc0(%rsp), %rdi
leaq 0xd0(%rsp), %rax
cmpq %rax, %rdi
je 0x242f6
movq 0xd0(%rsp), %rsi
incq %rsi
callq 0x53b0
leaq 0xa0(%rsp), %rbx
movq %rbx, %rdi
leaq 0x10(%rsp), %rsi
callq 0x1aa0a
movq %rbx, %rdi
leaq 0x30(%rsp), %rsi
callq 0x1aa0a
movq 0x68(%rsp), %rdx
movq 0x70(%rsp), %rcx
cmpq %rcx, %rdx
je 0x2435a
leaq 0x68(%rsp), %rdi
movq %rdx, %rsi
callq 0x25e12
movq 0x68(%rsp), %rdx
movq 0x70(%rsp), %rcx
cmpq %rcx, %rdx
je 0x2435a
leaq 0x68(%rsp), %rdi
movq %rcx, %rsi
callq 0x25e12
movq 0x68(%rsp), %rdx
movq 0x70(%rsp), %rcx
movq 0x88(%rsp), %rsi
leaq 0x80(%rsp), %rdi
callq 0x25e8e
leaq 0x68(%rsp), %rdi
callq 0x8206
movq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rax
cmpq %rax, %rdi
je 0x24395
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x53b0
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x243b1
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x53b0
addq $0x48, %r13
jmp 0x2423c
movq %r12, %rdi
callq 0x2a8d0
movq 0xe0(%rsp), %r14
movq %rax, %r13
movq %r12, %rdi
callq 0x2a8d0
movq 0x8(%rax), %rsi
movq 0x80(%rsp), %rdx
movq 0x88(%rsp), %rcx
movq %r13, %rdi
callq 0x25e8e
movq %r12, %rdi
callq 0x2a8d6
movq %rax, %rdi
leaq 0xa0(%rsp), %rsi
callq 0x2bd24
leaq 0x100(%rsp), %rdi
movq %r12, %rsi
movq 0xe8(%rsp), %rdx
movq 0xf0(%rsp), %rcx
callq 0x2ccff
movq %r12, %rdi
leaq 0x100(%rsp), %rbx
movq %rbx, %rsi
callq 0x2a92a
movq %rbx, %rdi
callq 0x181f0
movq 0x68(%r15), %rdi
testq %rdi, %rdi
je 0x24459
movq 0x78(%r15), %rsi
subq %rdi, %rsi
callq 0x53b0
leaq 0x50(%r15), %rdi
callq 0x253d4
leaq 0x38(%r15), %rdi
callq 0x181f0
leaq 0x20(%r15), %rdi
callq 0x8206
leaq 0x8(%r15), %rdi
callq 0x8206
movl $0x80, %esi
movq %r15, %rdi
callq 0x53b0
movq (%rsp), %rdi
movq 0x50(%rsp), %rsi
callq 0x262dc
movq (%rsp), %rdi
movq %rax, %rsi
callq 0x2635a
movq 0x58(%rsp), %r15
leaq 0xc(%r15), %rsi
movq 0x8(%r14), %rdx
cmpq %rdx, %rsi
je 0x244c5
subq %rsi, %rdx
movq %r15, %rdi
callq 0x55d0
movq 0x8(%r14), %rdx
leaq 0xa0(%rsp), %rdi
addq $-0xc, %rdx
movq %rdx, 0x8(%r14)
callq 0x8206
leaq 0x80(%rsp), %rdi
callq 0x8206
cmpq 0x8(%r14), %r15
jne 0x24099
addq $0x118, %rsp            # imm = 0x118
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
leaq 0x100(%rsp), %rdi
callq 0x181f0
jmp 0x245d8
jmp 0x245d5
jmp 0x245d5
jmp 0x245d5
jmp 0x245d5
jmp 0x245d5
jmp 0x245d5
jmp 0x245d5
jmp 0x24597
jmp 0x24597
movq %rax, %r14
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x245d8
movq 0x20(%rsp), %rsi
jmp 0x245c9
movq %rax, %r14
jmp 0x245a4
jmp 0x24597
movq %rax, %r14
movq 0xc0(%rsp), %rdi
leaq 0xd0(%rsp), %rax
cmpq %rax, %rdi
je 0x245a4
movq 0xd0(%rsp), %rsi
incq %rsi
callq 0x53b0
jmp 0x245a4
jmp 0x245d5
jmp 0x245d5
jmp 0x245d5
jmp 0x245d5
jmp 0x245d5
movq %rax, %r14
leaq 0x68(%rsp), %rdi
callq 0x8206
leaq 0x8(%rsp), %rdi
callq 0x25214
jmp 0x245d8
jmp 0x245b2
movq %rax, %r14
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x245d8
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x53b0
jmp 0x245d8
jmp 0x245d5
movq %rax, %r14
leaq 0xa0(%rsp), %rdi
callq 0x8206
leaq 0x80(%rsp), %rdi
callq 0x8206
movq %r14, %rdi
callq 0x5660