// File: /workspace/github_c_makefile_star2_O0/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:
subq $0x88, %rsp
movb %sil, %al
movq %rdi, 0x80(%rsp)
movb %al, 0x7f(%rsp)
movq %rdx, 0x70(%rsp)
movq %rcx, 0x68(%rsp)
movq %r8, 0x60(%rsp)
movb $0x1, 0x57(%rsp)
movb $0x1, 0x56(%rsp)
movl $0x0, 0x50(%rsp)
leaq 0x2e73(%rip), %rdi      # 0x365d1
movb $0x0, %al
callq 0x1090
movq 0x80(%rsp), %rax
movq %rax, 0x58(%rsp)
movl $0xffffffff, 0x4c(%rsp) # imm = 0xFFFFFFFF
cmpq $0x0, 0x58(%rsp)
je 0x33a18
movq 0x58(%rsp), %rax
cmpl $0x1, 0x10(%rax)
jle 0x33a03
movq 0x58(%rsp), %rdi
movq 0x68(%rsp), %rsi
callq 0x33440
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rdi
movq 0x60(%rsp), %rsi
callq 0x7bc0
movq %rax, 0x38(%rsp)
cmpq $0x0, 0x38(%rsp)
je 0x3387d
cmpb $0x0, 0x56(%rsp)
je 0x337d7
movb $0x0, 0x56(%rsp)
jmp 0x337e5
leaq 0x1c67(%rip), %rdi      # 0x35445
movb $0x0, %al
callq 0x1090
movl 0x4c(%rsp), %esi
movq 0x70(%rsp), %rax
movq 0x38(%rsp), %rcx
movq (%rcx), %rcx
movq 0x10(%rcx), %rcx
movslq 0x20(%rcx), %rcx
movl (%rax,%rcx,4), %edx
leaq 0x2de0(%rip), %rdi      # 0x365e8
movb $0x0, %al
callq 0x1090
movq 0x38(%rsp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
movq %rax, 0x30(%rsp)
cmpq $0x0, 0x30(%rsp)
je 0x3385b
movq 0x70(%rsp), %rax
movq 0x30(%rsp), %rcx
movq 0x10(%rcx), %rcx
movslq 0x20(%rcx), %rcx
movl (%rax,%rcx,4), %esi
leaq 0x2dae(%rip), %rdi      # 0x365f2
movb $0x0, %al
callq 0x1090
movq 0x30(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x30(%rsp)
jmp 0x33820
leaq 0x1863(%rip), %rdi      # 0x350c5
movb $0x0, %al
callq 0x1090
movq 0x60(%rsp), %rdi
movq 0x38(%rsp), %rsi
callq 0x20000
jmp 0x339e9
movb $0x0, 0x57(%rsp)
cmpb $0x0, 0x7f(%rsp)
je 0x339e7
movq 0x58(%rsp), %rdi
movq 0x68(%rsp), %rsi
callq 0x33440
movq %rax, 0x28(%rsp)
movq 0x28(%rsp), %rdi
movq 0x68(%rsp), %rsi
callq 0xacb0
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rdi
movq 0x20(%rsp), %rax
movl (%rax), %esi
movq 0x60(%rsp), %rdx
callq 0x12480
movq %rax, 0x18(%rsp)
cmpq $0x0, 0x18(%rsp)
je 0x339d8
movq 0x18(%rsp), %rax
movq 0x20(%rax), %rax
movq $0x0, 0x18(%rax)
movq 0x18(%rsp), %rdi
movq 0x40(%rsp), %rsi
callq 0xbc00
movq 0x18(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, 0x10(%rsp)
je 0x339c9
movl 0x50(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x50(%rsp)
cmpb $0x0, 0x56(%rsp)
je 0x33948
movq 0x10(%rsp), %rax
movq (%rax), %rax
movq 0x10(%rax), %rax
movl 0x20(%rax), %esi
leaq 0x2cbf(%rip), %rdi      # 0x365f9
movb $0x0, %al
callq 0x1090
movb $0x0, 0x56(%rsp)
jmp 0x33965
movq 0x10(%rsp), %rax
movq (%rax), %rax
movq 0x10(%rax), %rax
movl 0x20(%rax), %esi
leaq 0x2c99(%rip), %rdi      # 0x365f7
movb $0x0, %al
callq 0x1090
movq 0x10(%rsp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, 0x8(%rsp)
je 0x339a8
movq 0x8(%rsp), %rax
movq 0x10(%rax), %rax
movl 0x20(%rax), %esi
leaq 0x2c61(%rip), %rdi      # 0x365f2
movb $0x0, %al
callq 0x1090
movq 0x8(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x8(%rsp)
jmp 0x33976
leaq 0x1716(%rip), %rdi      # 0x350c5
movb $0x0, %al
callq 0x1090
movq 0x10(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x10(%rsp)
jmp 0x33906
movq 0x60(%rsp), %rdi
movq 0x18(%rsp), %rsi
callq 0x20000
movq 0x68(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x1fb30
jmp 0x339e9
movl 0x4c(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x4c(%rsp)
movq 0x68(%rsp), %rdi
movq 0x40(%rsp), %rsi
callq 0x1fb30
jmp 0x33a05
movq 0x58(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x58(%rsp)
jmp 0x3377a
cmpb $0x0, 0x57(%rsp)
je 0x33a2f
leaq 0x2d2f(%rip), %rdi      # 0x36755
movb $0x0, %al
callq 0x1090
jmp 0x33a3d
leaq 0x2bc7(%rip), %rdi      # 0x365fd
movb $0x0, %al
callq 0x1090
cmpb $0x0, 0x7f(%rsp)
je 0x33a73
cmpl $0x0, 0x50(%rsp)
je 0x33a5f
movl 0x50(%rsp), %esi
leaq 0x2bc1(%rip), %rdi      # 0x36617
movb $0x0, %al
callq 0x1090
jmp 0x33a71
movl 0x50(%rsp), %esi
leaq 0x2c00(%rip), %rdi      # 0x3666a
movb $0x0, %al
callq 0x1090
jmp 0x33a73
movb 0x57(%rsp), %al
addq $0x88, %rsp
retq
nop