// File: /workspace/github_cpp_makefile_star2_O2/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, 0x80(%rsp)
movq %rcx, 0x78(%rsp)
movq %rdx, 0x90(%rsp)
movq %rsi, 0x10(%rsp)
movq %rdi, 0x18(%rsp)
movq (%rdi), %rax
movq %rax, 0x8(%rsp)
leaq 0xb0(%rsp), %rbx
leaq 0xf8(%rsp), %r12
movq 0x18(%rsp), %rax
movq 0x8(%rsp), %r15
cmpq 0x8(%rax), %r15
je 0x1cfa9
movq 0x10(%rsp), %r14
movq %r14, %rdi
movq %r15, %rsi
callq 0x1d860
movq (%rax), %r13
leaq 0x4(%r15), %rax
movq %r14, %rdi
movq %rax, %r14
movq %rax, %rsi
callq 0x1d860
movq (%rax), %rax
movq %rax, (%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x40(%rsp)
andq $0x0, 0x50(%rsp)
movaps %xmm0, 0x60(%rsp)
andq $0x0, 0x70(%rsp)
movq %r13, %rdi
callq 0x223d0
movq (%rax), %rbp
movq %r13, %rdi
callq 0x223d0
cmpq 0x8(%rax), %rbp
je 0x1cd1c
movl (%rbp), %eax
cmpl (%r14), %eax
je 0x1cd16
movq %r13, %rdi
callq 0x223d0
movq %rax, %rdi
movq %rbp, %rsi
callq 0x1d8ae
jmp 0x1cceb
addq $0x48, %rbp
jmp 0x1cceb
movq (%rsp), %rdi
callq 0x223d0
movq (%rax), %rbp
movq (%rsp), %rdi
callq 0x223d0
cmpq 0x8(%rax), %rbp
je 0x1cd5f
movl (%rbp), %eax
movq 0x8(%rsp), %rcx
cmpl (%rcx), %eax
je 0x1cd59
movq (%rsp), %rdi
callq 0x223d0
movq %rax, %rdi
movq %rbp, %rsi
callq 0x1d8ae
jmp 0x1cd28
addq $0x48, %rbp
jmp 0x1cd28
movq %r14, 0x88(%rsp)
movq (%rsp), %rdi
callq 0x223a8
movq (%rax), %rbp
movq 0x8(%rax), %r14
cmpq %r14, %rbp
je 0x1cda8
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x54a0
movq %r13, %rdi
callq 0x223a8
movq %rax, %rdi
movq %rbx, %rsi
callq 0x14efa
movq %rbx, %rdi
callq 0x56f8
addq $0x20, %rbp
jmp 0x1cd77
movq (%rsp), %rdi
callq 0x223ae
movq (%rax), %rbp
movq 0x8(%rax), %r14
cmpq %r14, %rbp
je 0x1cde9
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x54a0
movq %r13, %rdi
callq 0x223ae
movq %rax, %rdi
movq %rbx, %rsi
callq 0x14efa
movq %rbx, %rdi
callq 0x56f8
addq $0x20, %rbp
jmp 0x1cdb8
movq (%rsp), %rdi
callq 0x223d0
movq (%rax), %rbp
movq 0x8(%rax), %r14
cmpq %r14, %rbp
je 0x1cedb
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x1d7ac
movq %r12, %rdi
leaq 0xb8(%rsp), %rsi
callq 0x54a0
leaq 0x20(%rsp), %rdi
movq %r12, %rsi
movq 0x10(%rsp), %rdx
movq 0x90(%rsp), %rcx
callq 0x2379e
movq %r12, %r15
movq %r12, %rdi
callq 0x56f8
leaq 0x60(%rsp), %r12
movq %r12, %rdi
leaq 0xb8(%rsp), %rsi
callq 0x14efa
movq %r12, %rdi
leaq 0xd8(%rsp), %rsi
callq 0x14efa
movq 0x28(%rsp), %rdx
movq 0x30(%rsp), %rcx
cmpq %rcx, %rdx
je 0x1ceae
leaq 0x28(%rsp), %rdi
movq %rdx, %rsi
callq 0x1d8b4
movq %r15, %r12
movq 0x28(%rsp), %rdx
movq 0x30(%rsp), %rcx
cmpq %rcx, %rdx
je 0x1ceb1
leaq 0x28(%rsp), %rdi
movq %rcx, %rsi
callq 0x1d8b4
movq 0x28(%rsp), %rdx
movq 0x30(%rsp), %rcx
jmp 0x1ceb1
movq %r15, %r12
movq 0x48(%rsp), %rsi
leaq 0x40(%rsp), %rdi
callq 0x1d8ba
leaq 0x28(%rsp), %rdi
callq 0x709c
movq %rbx, %rdi
callq 0x1d846
addq $0x48, %rbp
jmp 0x1cdf9
movq %r13, %rdi
callq 0x223a8
movq %rax, %rbp
movq %r13, %rdi
callq 0x223a8
movq 0x8(%rax), %rsi
movq 0x40(%rsp), %rdx
movq 0x48(%rsp), %rcx
movq %rbp, %rdi
callq 0x1d8ba
movq %r13, %rdi
callq 0x223ae
movq %rax, %rdi
leaq 0x60(%rsp), %rsi
callq 0x23394
leaq 0x98(%rsp), %rdi
movq %r13, %rsi
movq 0x78(%rsp), %rdx
movq 0x80(%rsp), %rcx
callq 0x23f9a
movq %r13, %rdi
leaq 0x98(%rsp), %r14
movq %r14, %rsi
callq 0x22402
movq %r14, %rdi
callq 0x12eaa
movq (%rsp), %r14
movq %r14, %rdi
callq 0x1d8da
movl $0x80, %esi
movq %r14, %rdi
callq 0x5390
movq 0x10(%rsp), %rdi
movq 0x88(%rsp), %rsi
callq 0x1e8fc
movq 0x18(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x1d910
movq %rax, 0x8(%rsp)
leaq 0x60(%rsp), %rdi
callq 0x709c
leaq 0x40(%rsp), %rdi
callq 0x709c
jmp 0x1cc87
addq $0x118, %rsp            # imm = 0x118
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x1d006
movq %rax, %rbx
leaq 0x98(%rsp), %rdi
callq 0x12eaa
jmp 0x1d039
jmp 0x1d006
jmp 0x1d006
jmp 0x1d006
jmp 0x1d006
jmp 0x1d006
jmp 0x1d006
jmp 0x1d006
jmp 0x1d00b
jmp 0x1d00b
jmp 0x1d00b
jmp 0x1d006
movq %rax, %rbx
jmp 0x1d018
movq %rax, %rbx
leaq 0xf8(%rsp), %rdi
callq 0x56f8
jmp 0x1d018
jmp 0x1d006
jmp 0x1d006
jmp 0x1d006
jmp 0x1d006
jmp 0x1d006
movq %rax, %rbx
jmp 0x1d039
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x709c
leaq 0xb0(%rsp), %rdi
callq 0x1d846
jmp 0x1d039
jmp 0x1d029
movq %rax, %rbx
leaq 0xb0(%rsp), %rdi
callq 0x56f8
leaq 0x60(%rsp), %rdi
callq 0x709c
leaq 0x40(%rsp), %rdi
callq 0x709c
movq %rbx, %rdi
callq 0x5610