#include<stk.h>
#include<LINK/stkWrapper/LINK_STk.h>
#include<LINK/stkWrapper/Wrapper.h>
#include<LINK/algorithm/Algorithms.h>

#include <stdio.h>
#include <stdlib.h>

static PRIMITIVE animation_run(SCM k)
{
        Graph *gr;
        if (!INTEGERP(k))
                Err("animation-run: bad arg 1, <integer> expected", k);
	int i = INTEGER(k);
	animationRun(i);
	return UNDEFINED;
}

static PRIMITIVE animation_done(SCM k)
{
        Graph *gr;
        if (!INTEGERP(k))
                Err("animation-done: bad arg 1, <integer> expected", k);
	int i = INTEGER(k);
	animationDone(i);
	return UNDEFINED;
}

static PRIMITIVE animation_continue(SCM k)
{
        Graph *gr;
        if (!INTEGERP(k))
                Err("animation-continue: bad arg 1, <integer> expected", k);
	int i = INTEGER(k);
	animationContinue(i);
	return UNDEFINED;
}

static PRIMITIVE animation_step(SCM k)
{
        Graph *gr;
        if (!INTEGERP(k))
                Err("animation-step: bad arg 1, <integer> expected", k);
	int i = INTEGER(k);
	animationStep(i);
	return UNDEFINED;
}

static PRIMITIVE animation_backup(SCM k)
{
        Graph *gr;
        if (!INTEGERP(k))
                Err("animation-backup: bad arg 1, <integer> expected", k);
	int i = INTEGER(k);
	animationBackup(i);
	return UNDEFINED;
}

static PRIMITIVE animation_break(SCM k)
{
        Graph *gr;
        if (!INTEGERP(k))
                Err("animation-break: bad arg 1, <integer> expected", k);
	int i = INTEGER(k);
	animationBreak(i);
	return UNDEFINED;
}

static PRIMITIVE animation_clearbreaks(SCM k)
{
        Graph *gr;
        if (!INTEGERP(k))
                Err("animation-clear-breaks: bad arg 1, <integer> expected", k);
	int i = INTEGER(k);
	animationClearBreaks(i);
	return UNDEFINED;
}

void gen_Animation_Wrapper()
{
        STk_add_new_cpp_primitive("animation-run", tc_subr_1,
                               (PRIMITIVE (*)(...))animation_run);
        STk_add_new_cpp_primitive("animation-done", tc_subr_1,
                               (PRIMITIVE (*)(...))animation_done);
        STk_add_new_cpp_primitive("animation-continue", tc_subr_1,
                               (PRIMITIVE (*)(...))animation_continue);
        STk_add_new_cpp_primitive("animation-step", tc_subr_1,
                               (PRIMITIVE (*)(...))animation_step);
        STk_add_new_cpp_primitive("animation-backup", tc_subr_1,
                               (PRIMITIVE (*)(...))animation_backup);
        STk_add_new_cpp_primitive("animation-clear-breaks", tc_subr_1,
                               (PRIMITIVE (*)(...))animation_clearbreaks);
        STk_add_new_cpp_primitive("animation-break", tc_subr_1,
                               (PRIMITIVE (*)(...))animation_break);
}
#include<stk.h>
#include<LINK/stkWrapper/LINK_STk.h>
#include<LINK/stkWrapper/Wrapper.h>
#include<LINK/algorithm/Algorithms.h>
#include<LINK/basic/Sequence.h>
#include<LINK/graph/Graph.h>
#include<LINK/graph/Edge.h>

#include <stdio.h>
#include <stdlib.h>

static PRIMITIVE BiconnectedComponentsCmd(SCM g)
{
    Graph *gr;
    if (!(gr = getGraph(g)))
	Err("biconnected-components: bad arg 1, graph expected", g);
    Set< Set<Vertex*> > s = BiconnectedComponents(gr);
    Set< Set<Vertex*> >* sp = new Set< Set<Vertex*> >(s);
    
    return STk_make_CXXwrapper(Wrapper<Set< Set<Vertex*> > >::type,
			       Wrapper<Set< Set<Vertex*> > >::name, 
			       (void *) sp, LINK_DYNAMIC);
}

static PRIMITIVE BiconnectedComponentsAnimCmd(SCM g, SCM view) 
{
    Graph *gr;
    
    if (!(gr = getGraph(g)))
	Err("biconnected-components: bad arg 1, graph expected", g);
    char *name = getViewName(view);
    int k = initAnimation();
    animationWindows(k, name);
    Set< Set<Vertex*> > s = BiconnectedComponents(gr,name);
    Set< Set<Vertex*> >* sp = new Set< Set<Vertex*> >(s);
    return STk_make_CXXwrapper(Wrapper<Set< Set<Vertex*> > >::type,
			       Wrapper<Set< Set<Vertex*> > >::name, 
			       (void *) sp, LINK_DYNAMIC);
}

void gen_BiconnectedComponents_Wrapper()
{
    STk_add_new_cpp_primitive("bcc", tc_subr_1,
		 (PRIMITIVE (*)(...))BiconnectedComponentsCmd);
    STk_add_new_cpp_primitive("bcc*", tc_subr_2,
		 (PRIMITIVE (*)(...))BiconnectedComponentsAnimCmd);
    STk_add_new_cpp_primitive("biconnected-components", tc_subr_1,
		 (PRIMITIVE (*)(...))BiconnectedComponentsCmd);
    STk_add_new_cpp_primitive("biconnected-components*", tc_subr_2,
		 (PRIMITIVE (*)(...))BiconnectedComponentsAnimCmd);
}
#include<stk.h>
#include<LINK/stkWrapper/LINK_STk.h>
#include<LINK/stkWrapper/Wrapper.h>
#include<LINK/algorithm/Algorithms.h>
#include<LINK/basic/Sequence.h>
#include<LINK/graph/Graph.h>
#include<LINK/graph/Edge.h>
#include<LINK/graph/Vertex.h>

#include <stdio.h>
#include <stdlib.h>

static PRIMITIVE BreadthFirstSearchAnimCmd(SCM parms, int len)
{
    SCM graph, view=UNBOUND, vertex=UNBOUND;
    Graph *gr;
    char *name;
    Vertex *v;
    int& v_type = Wrapper<Vertex*>::type;

    switch (len) {
	case 0: return UNDEFINED;
		break;
	case 1: graph = CAR(parms);
		break;
	case 2: graph = CAR(parms);
		view = CAR(CDR(parms));
		break;
	case 3: graph = CAR(parms);
		view = CAR(CDR(parms));
		vertex = CAR(CDR(CDR(parms)));
		break;
    }
    if (!(gr = getGraph(graph)))
	Err("bfs: bad arg 1, graph expected", graph);
    if ((len > 1) && (!(name = getViewName(view))))
	Err("bfs: bad arg 2, graph view expected", view);
    if ((len > 2) && (!CXX_TYPEP(vertex, v_type)))
	Err("bfs: bad arg 3, <vertex*> expected", vertex);
    Sequence<Vertex*> s; 
    Sequence<Vertex*>* sp;
    if (len > 1) {
    	int k = initAnimation();
    	animationWindows(k, name);
	if (len > 2) {
		v = *(Vertex**) CLASSDATA(vertex);
    		s = BreadthFirstSearch(gr,name,v);
	} else
    		s = BreadthFirstSearch(gr,name);
    } else 
    	s = BreadthFirstSearch(gr);
    sp = new Sequence<Vertex*>(s);
    return STk_make_CXXwrapper(Wrapper<Sequence<Vertex*> >::type,
			       Wrapper<Sequence<Vertex*> >::name, (void *) sp, LINK_DYNAMIC);
}

void gen_BreadthFirstSearch_Wrapper()
{
        STk_add_new_cpp_primitive("bfs", tc_lsubr,
				 (PRIMITIVE (*)(...))BreadthFirstSearchAnimCmd);
        STk_add_new_cpp_primitive("breadth-first-search", tc_lsubr,
				 (PRIMITIVE (*)(...))BreadthFirstSearchAnimCmd);
}
#include<stk.h>
#include<LINK/stkWrapper/LINK_STk.h>
#include<LINK/stkWrapper/Wrapper.h>
#include<LINK/algorithm/Algorithms.h>
#include<LINK/basic/Sequence.h>
#include<LINK/graph/Graph.h>
#include<LINK/graph/Edge.h>

#include <stdio.h>
#include <stdlib.h>

static PRIMITIVE DepthFirstSearchCmd(SCM g)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("dfs: bad arg 1, graph expected", g);
        Sequence<Vertex*> s = DepthFirstSearch(gr,0);
        Sequence<Vertex*>* sp = new Sequence<Vertex*>(s);

        return STk_make_CXXwrapper(Wrapper<Sequence<Vertex*> >::type,
                Wrapper<Sequence<Vertex*> >::name, (void *) sp, LINK_DYNAMIC);
}

static PRIMITIVE DepthFirstSearchAnimCmd(SCM g, SCM view)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("dfs: bad arg 1, graph expected", g);
	char *name = getViewName(view);
	int k = initAnimation();
	animationWindows(k, name);
        Sequence<Vertex*> s = DepthFirstSearch(gr,name);
        Sequence<Vertex*>* sp = new Sequence<Vertex*>(s);

        return STk_make_CXXwrapper(Wrapper<Sequence<Vertex*> >::type,
                Wrapper<Sequence<Vertex*> >::name, (void *) sp, LINK_DYNAMIC);
}

void gen_DepthFirstSearch_Wrapper()
{
        STk_add_new_cpp_primitive("dfs", tc_subr_1,
                               (PRIMITIVE (*)(...))DepthFirstSearchCmd);
        STk_add_new_cpp_primitive("dfs*", tc_subr_2,
                               (PRIMITIVE (*)(...))DepthFirstSearchAnimCmd);
        STk_add_new_cpp_primitive("depth-first-search", tc_subr_1,
                               (PRIMITIVE (*)(...))DepthFirstSearchCmd);
        STk_add_new_cpp_primitive("depth-first-search*", tc_subr_2,
                               (PRIMITIVE (*)(...))DepthFirstSearchAnimCmd);
}
#include<stk.h>
#include<LINK/stkWrapper/LINK_STk.h>
#include<LINK/stkWrapper/Wrapper.h>
#include<LINK/algorithm/Algorithms.h>
#include<LINK/basic/Set.h>
#include<LINK/graph/Graph.h>
#include<LINK/graph/Edge.h>

#include <stdio.h>
#include <stdlib.h>

static PRIMITIVE HamiltonianCyclesCmd(SCM g)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("directed-triangles: bad arg 1, graph expected", g);
        HamiltonianCycles(gr,0);
        return UNDEFINED;
}

void gen_HamiltonianCycles_Wrapper()
{
        STk_add_new_cpp_primitive("hamiltonian-cycles", tc_subr_1,
                               (PRIMITIVE (*)(...))HamiltonianCyclesCmd);
}
#include<stk.h>
#include<LINK/stkWrapper/LINK_STk.h>
#include<LINK/stkWrapper/Wrapper.h>
#include<LINK/algorithm/Algorithms.h>
#include<LINK/graph/Graph.h>
#include<LINK/graph/HyperGraph.h>
#include<LINK/graph/Edge.h>

#include <stdio.h>
#include <stdlib.h>

static PRIMITIVE GoldbergTarjanCmd(SCM parms, int len)
{
	if (len < 1)
                Err("goldberg-tarjan <graph*> <a|b|c>? <A|B>? <Y|?>?",NIL);

        Graph *gr;
	SCM   stk_graph = CAR(parms); // CAR,CDR: see stk.h
	SCM   args = CDR(parms);

        if (!(gr = getGraph(stk_graph))) // getGraph: stkUtils.cc
                Err("goldberg-tarjan: bad arg 1, graph expected", stk_graph);
	char vertexselection = LIFO;
	char relabelchoice   = GLOBAL;
	char labelingchoice  = GLOBAL;
	if (!NULLP(args)) {
		if (!INTEGERP(CAR(args)))
                	Err("goldberg-tarjan: bad arg 2, string or symbol",
							CAR(args));
		vertexselection = INTEGER(CAR(args));
		args = CDR(args);
	}
	if (!NULLP(args)) {
		if (!INTEGERP(CAR(args)))
                	Err("goldberg-tarjan: bad arg 3, string or symbol",
							CAR(args));
		relabelchoice = INTEGER(CAR(args));
		args = CDR(args);
	}
	if (!NULLP(args)) {
		if (!INTEGERP(CAR(args)))
                	Err("goldberg-tarjan: bad arg 4, string or symbol",
							CAR(args));
		labelingchoice = INTEGER(CAR(args));
		args = CDR(args);
	}
        int maxflow = GoldbergTarjan(gr,vertexselection,relabelchoice,
				  labelingchoice);
	return STk_makeinteger(maxflow);
}

void gen_GoldbergTarjan_Wrapper()
{
        STk_add_new_cpp_primitive("goldberg-tarjan", tc_lsubr,
                             (PRIMITIVE (*)(...))GoldbergTarjanCmd);
}
#include<stk.h>
#include<LINK/stkWrapper/LINK_STk.h>
#include<LINK/stkWrapper/Wrapper.h>
#include<LINK/algorithm/Algorithms.h>
#include<LINK/basic/Set.h>
#include<LINK/graph/Graph.h>
#include<LINK/graph/Edge.h>

#include <stdio.h>
#include <stdlib.h>

static PRIMITIVE IntToHexString(SCM i)
{
	if (!INTEGERP(i))
		err("int-to-hex-string: integer expected", i);
	int v = INTEGER(i);
        char str[80];
        sprintf(str, "%x", v);
	return STk_makestring(str);
}

static PRIMITIVE KruskalCmd(SCM g)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("kruskal: bad arg 1, graph expected", g);
        Set<Edge*> s = Kruskal(gr,0);
        Set<Edge*>* sp = new Set<Edge*>(s);

        return STk_make_CXXwrapper(Wrapper<Set<Edge*> >::type,
                Wrapper<Set<Edge*> >::name, (void *) sp, LINK_DYNAMIC);
}

static PRIMITIVE KruskalAnimCmd(SCM g, SCM view=0)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("kruskal: bad arg 1, graph expected", g);
	char *name = getViewName(view);
	if (name) {
		int k = initAnimation();
		animationWindows(k, name);
	}
        Set<Edge*> s = Kruskal(gr,name);
        Set<Edge*>* sp = new Set<Edge*>(s);

        return STk_make_CXXwrapper(Wrapper<Set<Edge*> >::type,
                Wrapper<Set<Edge*> >::name, (void *) sp, LINK_DYNAMIC);
}

void gen_Kruskal_Wrapper()
{
//        STk_add_new_cpp_primitive("kruskal", tc_subr_1,
//                               (PRIMITIVE (*)(...))KruskalCmd);
        STk_add_new_cpp_primitive("kruskal", tc_subr_1_or_2,
                               (PRIMITIVE (*)(...))KruskalAnimCmd);
        STk_add_new_cpp_primitive("int-to-hex-string", tc_subr_1,
                                    (PRIMITIVE (*)(...))IntToHexString);
}
#include<stk.h>
#include<LINK/stkWrapper/LINK_STk.h>
#include<LINK/stkWrapper/Wrapper.h>
#include<LINK/algorithm/Algorithms.h>
#include<LINK/basic/Set.h>
#include<LINK/graph/Graph.h>

#include <stdio.h>
#include <stdlib.h>

static PRIMITIVE MaximalCliqueCmd(SCM g)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("maximal-clique: bad arg 1, graph expected", g);
        Set<Vertex*> s = MaximalClique(gr,0);
        Set<Vertex*>* sp = new Set<Vertex*>(s);

        return STk_make_CXXwrapper(Wrapper<Set<Vertex*> >::type,
                Wrapper<Set<Vertex*> >::name, (void *) sp, LINK_DYNAMIC);
}

static PRIMITIVE MaximalCliqueAnimCmd(SCM g, SCM view)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("dfs: bad arg 1, graph expected", g);
	char *name = getViewName(view);
	int k = initAnimation();
	animationWindows(k, name);
        Set<Vertex*> s = MaximalClique(gr,name);
        Set<Vertex*>* sp = new Set<Vertex*>(s);

        return STk_make_CXXwrapper(Wrapper<Set<Vertex*> >::type,
                Wrapper<Set<Vertex*> >::name, (void *) sp, LINK_DYNAMIC);
}

void gen_MaximalClique_Wrapper()
{
        STk_add_new_cpp_primitive("maximal-clique", tc_subr_1,
                               (PRIMITIVE (*)(...))MaximalCliqueCmd);
        STk_add_new_cpp_primitive("maximal-clique*", tc_subr_2,
                               (PRIMITIVE (*)(...))MaximalCliqueAnimCmd);
}
#include<stk.h>
#include<LINK/stkWrapper/LINK_STk.h>
#include<LINK/stkWrapper/Wrapper.h>
#include<LINK/algorithm/Algorithms.h>
#include<LINK/basic/Set.h>
#include<LINK/graph/Graph.h>
#include<LINK/graph/Edge.h>

#include <stdio.h>
#include <stdlib.h>

static PRIMITIVE TrianglesCmd(SCM g)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("directed-triangles: bad arg 1, graph expected", g);
        Triangles(gr,0);
        return UNDEFINED;
}

void gen_Triangles_Wrapper()
{
        STk_add_new_cpp_primitive("find-triangles", tc_subr_1,
                               (PRIMITIVE (*)(...))TrianglesCmd);
}
#include<stk.h>
#include<LINK/stkWrapper/LINK_STk.h>
#include<LINK/stkWrapper/Wrapper.h>
#include<LINK/algorithm/Algorithms.h>
#include<LINK/basic/Sequence.h>
#include<LINK/graph/Graph.h>
#include<LINK/graph/Edge.h>

#include <stdio.h>
#include <stdlib.h>

static PRIMITIVE TopologicalSortCmd(SCM g)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("topsort: bad arg 1, graph expected", g);
        Sequence<Vertex*> s = TopologicalSort(gr);
        Sequence<Vertex*>* sp = new Sequence<Vertex*>(s);

        return STk_make_CXXwrapper(Wrapper<Sequence<Vertex*> >::type,
                Wrapper<Sequence<Vertex*> >::name, (void *) sp, LINK_DYNAMIC);
}

static PRIMITIVE TopologicalSortAnimCmd(SCM g, SCM view) {
    Graph *gr;
    
    if (!(gr = getGraph(g)))
	Err("topsort: bad arg 1, graph expected", g);
    char *name = getViewName(view);
    int k = initAnimation();
    animationWindows(k, name);
    Sequence<Vertex*> s = TopologicalSort(gr,name);
    Sequence<Vertex*>* sp = new Sequence<Vertex*>(s);
    return STk_make_CXXwrapper(Wrapper<Sequence<Vertex*> >::type,
			       Wrapper<Sequence<Vertex*> >::name, (void *) sp, LINK_DYNAMIC);
}

void gen_TopologicalSort_Wrapper()
{
    STk_add_new_cpp_primitive("topsort", tc_subr_1,
			      (PRIMITIVE (*)(...))TopologicalSortCmd);
    STk_add_new_cpp_primitive("topsort*", tc_subr_2,
			      (PRIMITIVE (*)(...))TopologicalSortAnimCmd);
    STk_add_new_cpp_primitive("topological-sort", tc_subr_1,
			      (PRIMITIVE (*)(...))TopologicalSortCmd);
    STk_add_new_cpp_primitive("topological-sort*", tc_subr_2,
			      (PRIMITIVE (*)(...))TopologicalSortAnimCmd);
}
#include<stk.h>
#include<LINK/stkWrapper/LINK_STk.h>
#include<LINK/stkWrapper/Wrapper.h>
#include<LINK/algorithm/Algorithms.h>
#include<LINK/basic/Sequence.h>
#include<LINK/graph/Graph.h>
#include<LINK/graph/Edge.h>

#include <stdio.h>
#include <stdlib.h>

static PRIMITIVE StronglyConnectedComponentsCmd(SCM g)
{
    Graph *gr;
    if (!(gr = getGraph(g)))
	Err("strongly-connected-components: bad arg 1, graph expected", g);
    Set< Set<Vertex*> > s = StronglyConnectedComponents(gr);
    Set< Set<Vertex*> >* sp = new Set< Set<Vertex*> >(s);
    
    return STk_make_CXXwrapper(Wrapper<Set< Set<Vertex*> > >::type,
			       Wrapper<Set< Set<Vertex*> > >::name, 
			       (void *) sp, LINK_DYNAMIC);
}

static PRIMITIVE StronglyConnectedComponentsAnimCmd(SCM g, SCM view) 
{
    Graph *gr;
    
    if (!(gr = getGraph(g)))
	Err("strongly-connected-components: bad arg 1, graph expected", g);
    char *name = getViewName(view);
    int k = initAnimation();
    animationWindows(k, name);
    Set< Set<Vertex*> > s = StronglyConnectedComponents(gr,name);
    Set< Set<Vertex*> >* sp = new Set< Set<Vertex*> >(s);
    return STk_make_CXXwrapper(Wrapper<Set< Set<Vertex*> > >::type,
			       Wrapper<Set< Set<Vertex*> > >::name, 
			       (void *) sp, LINK_DYNAMIC);
}

void gen_StronglyConnectedComponents_Wrapper()
{
    STk_add_new_cpp_primitive("scc", tc_subr_1,
		 (PRIMITIVE (*)(...))StronglyConnectedComponentsCmd);
    STk_add_new_cpp_primitive("scc*", tc_subr_2,
		 (PRIMITIVE (*)(...))StronglyConnectedComponentsAnimCmd);
    STk_add_new_cpp_primitive("strongly-connected-components", tc_subr_1,
		 (PRIMITIVE (*)(...))StronglyConnectedComponentsCmd);
    STk_add_new_cpp_primitive("strongly-connected-components*", tc_subr_2,
		 (PRIMITIVE (*)(...))StronglyConnectedComponentsAnimCmd);
}
