//genMethods "-g" "-t" "Edge*" "-I" "LINK/graph/Edge.h" "-d" "graph" "-y" "display_edgeptr" "-m" "mark_edgeptr" "-w" "free_edgeptr" 

#include <stk.h>
#include <LINK/stkWrapper/LINK_STk.h>

#include <LINK/graph/Edge.h>

#include <LINK/stkWrapper/Wrapper.h>
#include <LINK/stkWrapper/Register.h>

void display_edgeptr(SCM, SCM, int);
void mark_edgeptr(SCM);
void free_edgeptr(SCM);

typedef Edge* _Edge_;

#define _Edge_DATA(x) ((Edge**) (EXTDATA(x)))
#define _Edge_IS_DATA(x) (TYPEP(x, tc_CXXwrapper) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Edge* >::type))
#define _Edge_ISNT_DATA(x) (!IS_DATA(x))

#define _Edge_CXX_DATA(x) (*(Edge**) (EXTDATA(VAL(x))))
#define _Edge_CXX_IS_DATA(x) (INSTANCEP(x) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Edge* >::type))
#define _Edge_CXX_ISNT_DATA(x) (!CXX_IS_DATA(x))

#include<strstream.h>
void display_edgeptr(SCM c, SCM port, int mode)
{
        ostrstream oss;
	if (*_Edge_DATA(c));
        	oss << **_Edge_DATA(c);
        oss << ends;
        char *buffer = oss.str();
        Puts(buffer, FILEPTR(port));
        delete buffer;
}

void mark_edgeptr(SCM p)
{
        //cout << "mark_edgeptr" << endl;
        Register<Edge>::markEntry(*_Edge_DATA(p));
}

void free_edgeptr(SCM p)
{
        //cout << "free_edgeptr" << endl;
        if (!EXTSTATICP(p)) {
                delete _Edge_DATA(p);
        }
}


static PRIMITIVE SizeEdgeCmd(SCM e)
{
        Edge *edge;
        int& etype = Wrapper<Edge*>::type;
        if (!CXX_TYPEP(e, etype))
                Err("size-edge: bad arg 1, <edge*> expected", e);
	edge = * (Edge**) CLASSDATA(e);
        int sz = edge->size();
        SCM result = STk_makeinteger(sz);
        return result;
}

static PRIMITIVE VerticesEdgeCmd(SCM e)
{
        Edge *edge;
        int& etype = Wrapper<Edge*>::type;
        if (!CXX_TYPEP(e, etype))
                Err("edge-vertices: bad arg 1, <edge*> expected", e);
	edge = * (Edge**) CLASSDATA(e);
        Collection<Vertex*>* s = edge->vertices();
	if (s->sortedQ()) { // undirected edge
		Set<Vertex*> *ss = new Set<Vertex*>(*s);
		return STk_make_CXXwrapper(Wrapper<Set<Vertex*> >::type,
               	    Wrapper<Set<Vertex*> >::name, (void *) ss, LINK_DYNAMIC);
	} else {
		Sequence<Vertex*> *sq = new Sequence<Vertex*>(*s);
		return STk_make_CXXwrapper(Wrapper<Sequence<Vertex*> >::type,
               	    Wrapper<Sequence<Vertex*> >::name,(void *)sq,LINK_DYNAMIC);
	}
}



// define your new methods above 
// and register them using STk_add_new_cpp_primitive() below

void genExtra_Edge_Methods() 
{
        STk_add_new_cpp_primitive("size-edge", tc_subr_1,
                                    (PRIMITIVE (*)(...))SizeEdgeCmd);
        STk_add_new_cpp_primitive("edge-vertices", tc_subr_1,
                                    (PRIMITIVE (*)(...))VerticesEdgeCmd);
	addOneArgMethod("size",
			Wrapper<_Edge_ >::name,
			"size-edge", LINK_OVL);
	addOneArgMethod("vertices",
			Wrapper<_Edge_ >::name,
			"edge-vertices", LINK_OVL);
}
