// File: /workspace/github_c_makefile_star2_O1/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 0x246d(%rip), %rdi      # 0x21587
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x10b0
testq %r13, %r13
je 0x1f339
movl $0xffffffff, 0x1c(%rsp) # imm = 0xFFFFFFFF
movb $0x1, %al
movl %eax, 0x8(%rsp)
leaq 0x2467(%rip), %r14      # 0x215a8
movb $0x1, %al
movl %eax, 0x10(%rsp)
xorl %ebp, %ebp
movq %r15, 0x28(%rsp)
movq %rbx, 0x20(%rsp)
cmpl $0x2, 0x10(%r13)
jl 0x1f31d
movq %r13, %rdi
movq %rbx, %rsi
callq 0x1ef8e
movq %rax, 0x30(%rsp)
movq %rax, %rdi
movq %r15, %rsi
callq 0x67b1
testq %rax, %rax
je 0x1f20f
movq %rax, %rbx
cmpb $0x0, 0x10(%rsp)
jne 0x1f19a
leaq 0x125a(%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 0x23ee(%rip), %rdi      # 0x2159e
movl 0x1c(%rsp), %esi
xorl %eax, %eax
callq 0x10b0
movq (%rbx), %rax
movq 0x8(%rax), %r15
testq %r15, %r15
je 0x1f1e3
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 0x1f1c2
movl $0x5d, %edi
callq 0x1040
movq 0x28(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
callq 0x14b75
movl $0x0, 0x10(%rsp)
movq 0x20(%rsp), %rbx
jmp 0x1f30c
cmpb $0x0, 0x18(%rsp)
je 0x1f32c
movq %r13, %rdi
movq 0x20(%rsp), %rbx
movq %rbx, %rsi
callq 0x1ef8e
movq %rax, %rdi
movq %rbx, %rsi
callq 0x7f7e
movl (%rax), %esi
movq %rax, 0x8(%rsp)
movq %rax, %rdi
movq %r15, %rdx
callq 0xc21c
testq %rax, %rax
je 0x1f2f7
movq 0x20(%rax), %rcx
movq $0x0, 0x18(%rcx)
movq %rax, %rbx
movq %rax, %rdi
movq 0x30(%rsp), %rsi
callq 0x873a
cmpb $0x0, 0x10(%rsp)
leaq 0x2337(%rip), %rdi      # 0x215af
leaq 0x232e(%rip), %rax      # 0x215ad
cmoveq %rax, %rdi
movq %rbx, 0x10(%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 0x1f2bc
movq 0x10(%r15), %rax
movl 0x20(%rax), %esi
movq %r14, %rdi
xorl %eax, %eax
callq 0x10b0
movq 0x8(%r15), %r15
jmp 0x1f2a0
incl %ebp
movl $0x5d, %edi
callq 0x1040
movq 0x18(%rbx), %rbx
leaq 0x22da(%rip), %rdi      # 0x215ad
testq %rbx, %rbx
jne 0x1f288
movq 0x28(%rsp), %r15
movq %r15, %rdi
movq 0x10(%rsp), %rsi
callq 0x14b75
movl $0x0, 0x10(%rsp)
movq 0x20(%rsp), %rbx
movq %rbx, %rdi
movq 0x8(%rsp), %rsi
callq 0x14832
movl $0x0, 0x8(%rsp)
decl 0x1c(%rsp)
movq %rbx, %rdi
movq 0x30(%rsp), %rsi
callq 0x14832
movq 0x18(%r13), %r13
testq %r13, %r13
jne 0x1f153
jmp 0x1f33f
movl $0x0, 0x8(%rsp)
jmp 0x1f205
movb $0x1, %al
movl %eax, 0x8(%rsp)
movl 0x8(%rsp), %ebx
testb %bl, %bl
leaq 0x2267(%rip), %rax      # 0x215b3
leaq 0x23b6(%rip), %rdi      # 0x21709
cmoveq %rax, %rdi
xorl %eax, %eax
callq 0x10b0
cmpb $0x0, 0x18(%rsp)
je 0x1f384
testl %ebp, %ebp
je 0x1f374
leaq 0x225d(%rip), %rdi      # 0x215cd
movl %ebp, %esi
jmp 0x1f37d
leaq 0x22a5(%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