// File: /workspace/github_c_makefile_star2_O3/pwelke[P]GraphMiningTools/executables/outerplanaritytest.c
// Function: listHamiltonianCycles
char listHamiltonianCycles(struct ShallowGraph* biconnectedComponents, char extendToHamiltonianBlocks, int* originalIDs, struct GraphPool* gp, struct ShallowGraphPool* sgp) {
    /**
    An outerplanar graph is a graph that can be drawn in the plane such that
    (1) edges only intersect at vertices and
    (2) each vertex can be reached from the outer face without crossing an edge.

    A graph is outerplanar if and only if each of its biconnected components is outerplanar.
    */ 
    struct ShallowGraph* comp;
    char isOuterplanar = 1;
    char isFirstCycle = 1; // for pretty printing
    int nonOuterplanarHamiltonianCycles = 0;
    int componentNumber;

    printf("\"hamiltonianCycles\": {");

    for (comp = biconnectedComponents, componentNumber=-1; comp!=NULL; comp=comp->next) {
        if (comp->m > 1) {
            struct Graph* block = shallowGraphToGraphWithIDs(comp, gp);
            // returns null if block is not outerplanar
            struct ShallowGraph* hamiltonianCycle = __getCycleAndDiagonals(block, sgp);

            if (hamiltonianCycle != NULL) {
                if (isFirstCycle) {
                    isFirstCycle = 0;
                } else {
                    printf(", ");
                }
                printf("\"%i\": [%i", componentNumber, originalIDs[hamiltonianCycle->edges->startPoint->lowPoint]);

                struct VertexList* e;
                for (e = hamiltonianCycle->edges->next; e!=NULL; e=e->next) {
                    printf(", %i", originalIDs[e->startPoint->lowPoint]);
                }
                printf("]");

                
                
                // cleanup
                dumpShallowGraphCycle(sgp, hamiltonianCycle);

            } else {
                isOuterplanar = 0;
                if (extendToHamiltonianBlocks) {
                    struct Graph* newBlock = shallowGraphToGraphWithIDs(comp, gp);
                    struct Graph* blockCopy = cloneGraph(newBlock, gp);
                    struct ShallowGraph* hamiltonianCycles = listCyclesOfLength(blockCopy, blockCopy->n, sgp);
                    if (hamiltonianCycles) {
                        // listCyclesOfLength returns a cycle of ShallowGraphs which needs to be broken
                        hamiltonianCycles->prev->next = NULL;
                        rebaseShallowGraphs(hamiltonianCycles, block);

                        for (struct ShallowGraph* h=hamiltonianCycles; h!=NULL; h=h->next) {
                            nonOuterplanarHamiltonianCycles += 1;
                            if (isFirstCycle) {
                                printf("[%i", h->edges->startPoint->lowPoint);
                                isFirstCycle = 0;
                            } else {
                                printf(", [%i", h->edges->startPoint->lowPoint);
                            }
                            struct VertexList* e;
                            for (e = h->edges->next; e!=NULL; e=e->next) {
                                printf(", %i", e->startPoint->lowPoint);
                            }
                            printf("]");
                        }
                        // cleanup
                        dumpShallowGraphCycle(sgp, hamiltonianCycles);
                    }  
                    dumpGraph(gp, blockCopy);
                }
            }
            --componentNumber;
            dumpGraph(gp, block);
        } 	
    }

    if (isOuterplanar) {
        printf("}, \"isOuterplanar\": true");
    } else {
        printf("}, \"isOuterplanar\": false");
    }

    if (extendToHamiltonianBlocks) {
        if (nonOuterplanarHamiltonianCycles) {
            printf(", \"hasNonOuterplanarHamiltonianBlock\": true, \"nonOuterplanarHamiltonianCycles\": %i", nonOuterplanarHamiltonianCycles);
        } else {
            printf(", \"hasNonOuterplanarHamiltonianBlock\": false, \"nonOuterplanarHamiltonianCycles\": %i", nonOuterplanarHamiltonianCycles);
        }
    }

    return isOuterplanar;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %r8, %r15
movq %rcx, %rbx
movq %rdx, %r12
movl %esi, 0x18(%rsp)
movq %rdi, %r13
leaq 0x25e6(%rip), %rdi      # 0x21587
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x10b0
testq %r13, %r13
je 0x1f1da
movl $0xffffffff, 0x1c(%rsp) # imm = 0xFFFFFFFF
movb $0x1, %al
movl %eax, 0x10(%rsp)
leaq 0x25e0(%rip), %r14      # 0x215a8
movb $0x1, %al
movl %eax, 0x8(%rsp)
xorl %ebp, %ebp
movq %r15, 0x28(%rsp)
movq %rbx, 0x20(%rsp)
cmpl $0x2, 0x10(%r13)
jl 0x1f1a4
movq %r13, %rdi
movq %rbx, %rsi
callq 0x1ee0e
movq %rax, 0x30(%rsp)
movq %rax, %rdi
movq %r15, %rsi
callq 0x6817
testq %rax, %rax
je 0x1f096
movq %rax, %rbx
cmpb $0x0, 0x8(%rsp)
jne 0x1f021
leaq 0x13d3(%rip), %rdi      # 0x203ed
xorl %eax, %eax
callq 0x10b0
movq (%rbx), %rax
movq 0x10(%rax), %rax
movslq 0x20(%rax), %rax
movl (%r12,%rax,4), %edx
leaq 0x2567(%rip), %rdi      # 0x2159e
movl 0x1c(%rsp), %esi
xorl %eax, %eax
callq 0x10b0
movq (%rbx), %rax
movq 0x8(%rax), %r15
testq %r15, %r15
je 0x1f06a
movq 0x10(%r15), %rax
movslq 0x20(%rax), %rax
movl (%r12,%rax,4), %esi
movq %r14, %rdi
xorl %eax, %eax
callq 0x10b0
movq 0x8(%r15), %r15
jmp 0x1f049
movl $0x5d, %edi
callq 0x1040
movq 0x28(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
callq 0x14a56
movl $0x0, 0x8(%rsp)
movq 0x20(%rsp), %rbx
jmp 0x1f193
cmpb $0x0, 0x18(%rsp)
je 0x1f1b3
movq %r13, %rdi
movq 0x20(%rsp), %rbx
movq %rbx, %rsi
callq 0x1ee0e
movq %rax, %rdi
movq %rbx, %rsi
callq 0x7fc9
movl (%rax), %esi
movq %rax, 0x10(%rsp)
movq %rax, %rdi
movq %r15, %rdx
callq 0xc17c
testq %rax, %rax
je 0x1f17e
movq 0x20(%rax), %rcx
movq $0x0, 0x18(%rcx)
movq %rax, %rbx
movq %rax, %rdi
movq 0x30(%rsp), %rsi
callq 0x87b6
cmpb $0x0, 0x8(%rsp)
leaq 0x24b0(%rip), %rdi      # 0x215af
leaq 0x24a7(%rip), %rax      # 0x215ad
cmoveq %rax, %rdi
movq %rbx, 0x8(%rsp)
movq (%rbx), %rax
movq 0x10(%rax), %rax
movl 0x20(%rax), %esi
xorl %eax, %eax
callq 0x10b0
movq (%rbx), %rax
movq 0x8(%rax), %r15
testq %r15, %r15
je 0x1f143
movq 0x10(%r15), %rax
movl 0x20(%rax), %esi
movq %r14, %rdi
xorl %eax, %eax
callq 0x10b0
movq 0x8(%r15), %r15
jmp 0x1f127
incl %ebp
movl $0x5d, %edi
callq 0x1040
movq 0x18(%rbx), %rbx
leaq 0x2453(%rip), %rdi      # 0x215ad
testq %rbx, %rbx
jne 0x1f10f
movq 0x28(%rsp), %r15
movq %r15, %rdi
movq 0x8(%rsp), %rsi
callq 0x14a56
movl $0x0, 0x8(%rsp)
movq 0x20(%rsp), %rbx
movq %rbx, %rdi
movq 0x10(%rsp), %rsi
callq 0x14700
movl $0x0, 0x10(%rsp)
decl 0x1c(%rsp)
movq %rbx, %rdi
movq 0x30(%rsp), %rsi
callq 0x14700
movq 0x18(%r13), %r13
testq %r13, %r13
jne 0x1efda
jmp 0x1f1c0
movl $0x0, 0x10(%rsp)
jmp 0x1f08c
movl 0x10(%rsp), %ebx
testb %bl, %bl
leaq 0x23e6(%rip), %rax      # 0x215b3
leaq 0x2533(%rip), %rdi      # 0x21707
cmoveq %rax, %rdi
jmp 0x1f1e3
movb $0x1, %bl
leaq 0x2524(%rip), %rdi      # 0x21707
xorl %eax, %eax
callq 0x10b0
cmpb $0x0, 0x18(%rsp)
je 0x1f210
testl %ebp, %ebp
je 0x1f200
leaq 0x23d1(%rip), %rdi      # 0x215cd
movl %ebp, %esi
jmp 0x1f209
leaq 0x2419(%rip), %rdi      # 0x21620
xorl %esi, %esi
xorl %eax, %eax
callq 0x10b0
movl %ebx, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq