// File: /workspace/github_c_makefile_star2_O2/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, 0x20(%rsp)
movq %rcx, %rbx
movq %rdx, %r12
movl %esi, 0x10(%rsp)
movq %rdi, %r13
leaq 0x2304(%rip), %rdi      # 0x1e527
xorl %eax, %eax
callq 0x10b0
movb $0x1, %r14b
pushq $-0x1
popq %rax
movl %eax, 0x14(%rsp)
leaq 0x230d(%rip), %r15      # 0x1e548
xorl %ebp, %ebp
movb $0x1, %al
movl %eax, 0x8(%rsp)
movq %rbx, 0x18(%rsp)
testq %r13, %r13
je 0x1c409
cmpl $0x2, 0x10(%r13)
jl 0x1c3f3
movq %r13, %rdi
movq %rbx, %rsi
callq 0x1c090
movq %rax, 0x28(%rsp)
movq %rax, %rdi
movq 0x20(%rsp), %rsi
callq 0x475b
testq %rax, %rax
je 0x1c2fb
movq %rax, %rbx
testb %r14b, %r14b
jne 0x1c294
leaq 0x1160(%rip), %rdi      # 0x1d3ed
xorl %eax, %eax
callq 0x10b0
movq (%rbx), %rax
movq 0x10(%rax), %rax
movslq 0x20(%rax), %rax
movl (%r12,%rax,4), %edx
leaq 0x2294(%rip), %rdi      # 0x1e53e
movl 0x14(%rsp), %esi
xorl %eax, %eax
callq 0x10b0
movq (%rbx), %r14
movq 0x8(%r14), %r14
testq %r14, %r14
je 0x1c2d9
movq 0x10(%r14), %rax
movslq 0x20(%rax), %rax
movl (%r12,%rax,4), %esi
movq %r15, %rdi
xorl %eax, %eax
callq 0x10b0
jmp 0x1c2b8
pushq $0x5d
popq %rdi
callq 0x1040
movq 0x20(%rsp), %rdi
movq %rbx, %rsi
callq 0x11888
xorl %r14d, %r14d
movq 0x18(%rsp), %rbx
jmp 0x1c3e2
cmpb $0x0, 0x10(%rsp)
je 0x1c3fc
movq %r13, %rdi
movq 0x18(%rsp), %rbx
movq %rbx, %rsi
callq 0x1c090
movq %rax, %rdi
movq %rbx, %rsi
callq 0x5dac
movl (%rax), %esi
movq %rax, 0x8(%rsp)
movq %rax, %rdi
movq 0x20(%rsp), %rdx
callq 0x9b5e
testq %rax, %rax
je 0x1c3cd
movq 0x20(%rax), %rcx
andq $0x0, 0x18(%rcx)
movq %rax, %rbx
movq %rax, %rdi
movq 0x28(%rsp), %rsi
callq 0x64e8
movq %rbx, 0x30(%rsp)
testq %rbx, %rbx
je 0x1c3b9
incl %ebp
testb %r14b, %r14b
movq (%rbx), %rax
movq 0x10(%rax), %rax
movl 0x20(%rax), %esi
leaq 0x21d8(%rip), %rdi      # 0x1e54f
leaq 0x21cf(%rip), %rax      # 0x1e54d
cmoveq %rax, %rdi
xorl %eax, %eax
callq 0x10b0
movq (%rbx), %r14
movq 0x8(%r14), %r14
testq %r14, %r14
je 0x1c3a8
movq 0x10(%r14), %rax
movl 0x20(%rax), %esi
movq %r15, %rdi
xorl %eax, %eax
callq 0x10b0
jmp 0x1c38c
pushq $0x5d
popq %rdi
callq 0x1040
movq 0x18(%rbx), %rbx
xorl %r14d, %r14d
jmp 0x1c35c
movq 0x20(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x11888
movq 0x18(%rsp), %rbx
movq %rbx, %rdi
movq 0x8(%rsp), %rsi
callq 0x1166e
movl $0x0, 0x8(%rsp)
decl 0x14(%rsp)
movq %rbx, %rdi
movq 0x28(%rsp), %rsi
callq 0x1166e
movq 0x18(%r13), %r13
jmp 0x1c248
movl $0x0, 0x8(%rsp)
jmp 0x1c2f1
movl 0x8(%rsp), %ebx
testb %bl, %bl
leaq 0x213d(%rip), %rax      # 0x1e553
leaq 0x228a(%rip), %rdi      # 0x1e6a7
cmoveq %rax, %rdi
xorl %eax, %eax
callq 0x10b0
cmpb $0x0, 0x10(%rsp)
je 0x1c44e
testl %ebp, %ebp
je 0x1c43e
leaq 0x2133(%rip), %rdi      # 0x1e56d
movl %ebp, %esi
jmp 0x1c447
leaq 0x217b(%rip), %rdi      # 0x1e5c0
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