/* This software is distributed under the Lesser General Public License */
// 
// L      S      D
// Leda & Sgraph Do it
//
//
// Author: Dirk Heider
// email: heider@fmi.uni-passau.de
// Changes and adjustment to graphlet: Walter Bachl
// Additional Changes: Michael Himsolt
//

///////////////////////////////////////////////////////////
//
// Main Programm to call the algorithms which are
// implemented in sgraph.
//
///////////////////////////////////////////////////////////

#include <gt_base/Graphlet.h>

#include <gt_tcl/Tcl.h>
#include <gt_tcl/Tcl_Algorithm.h>
#include <gt_tcl/Graphscript.h>
#include <gt_base/NEI.h>

// LSD standard includes
#include "lsd/lsdstd.h"
#include "gt_lsd.h"

#include "../gt_tree_layout/tree_check.h"
#include "tree_layout_walker_export.h"
#include "walker_checks.h"
#include "gt_lsd_tree_layout_walker.h"


//////////////////////////////////////////
//
// Tree Layout Walker
//
//////////////////////////////////////////


//
// Algorithm 
//

GT_Tree_Walker::GT_Tree_Walker (const string& name) : GT_Algorithm (name)
{
    the_vertical = 64;
    the_sibling = 16;
    the_subtree = 32;
}

GT_Tree_Walker::~GT_Tree_Walker ()
{
}

int GT_Tree_Walker::run (GT_Graph& g)
{
    // check on empty graph
    if (g.leda().number_of_nodes() < 1 ) {
	return GT_OK;
    }

    // hide edges
    list<edge> edges;
    hide_selfloops (g.attached(), edges);
    hide_multiedges (g.attached(), edges);
    //graph leda = g.leda();
    LSD   lsd;

    lsd.gt_graph (&g);

    lsd.init_call();
    call_tree_layout_walker(lsd.proc_info(), vertical_separation(), 
	sibling_separation(), subtree_separation());
    lsd.clean_up();

    // restore hidden edges
    list<edge>::iterator it;
    list<edge>::iterator end = edges.end();

    for (it = edges.begin (); it != end; ++it) {
	g.attached()->restore_edge (*it);
    }

    remove_all_bends (g);
    adjust_coordinates (g, 10, 10);
    reset_NEIs (g);
    return GT_OK;
}

int GT_Tree_Walker::check (GT_Graph& g, string& message)
{
    // check on empty graph
    if (g.attached()->number_of_nodes() < 1 ) {
	message = "The graph is empty.";
	return GT_OK;
    }

    if (check_directed_tree(g, message, the_nodes, the_edges)) {
	return GT_OK;
    }

    return GT_ERROR;
}

//
// Tcl Wrapper
//

GT_Tcl_Tree_Walker::GT_Tcl_Tree_Walker (const string& name) :
	GT_Tcl_Algorithm<GT_Tree_Walker> (name)
{
}

GT_Tcl_Tree_Walker::~GT_Tcl_Tree_Walker ()
{
}

int GT_Tcl_Tree_Walker::parse (GT_Tcl_info& info, int& index,
    GT_Tcl_Graph* /* g*/)
{
    int code = TCL_OK;

    if(info.argv(index)[0] == '-') {

        if (!strcmp(info.argv(index),"-vertical_separation")) {
            code = Tcl_GetInt (info.interp(), info.argv(++index), &the_vertical);
	} else if (!strcmp(info.argv(index),"-sibling_separation")){
            code = Tcl_GetInt (info.interp(), info.argv(++index), &the_sibling);
	} else if (!strcmp(info.argv(index),"-subtree_separation")){
            code = Tcl_GetInt (info.interp(), info.argv(++index), &the_subtree);
	}
    }

    index++;
    return code;
}



//////////////////////////////////////////////
//
// Main Initialization function for interface
//
// Tcl/Tk naming conventions
//
//////////////////////////////////////////////

int Gt_lsd_tree_layout_walker_Init (Tcl_Interp* interp)
{
    int code = 0;

    GT_Tcl_Algorithm_Command* layout_tree =
	new GT_Tcl_Tree_Walker ("layout_tree_walker");
    code = layout_tree->install(interp);
    if (code == TCL_ERROR) {
	return code;
    }

    char version[(2+2+2) + 2 + 1];
    sprintf (version, "%d.%d.%d",
	GT_MAJOR_VERSION, GT_MINOR_VERSION, GT_MINI_VERSION);
    code = Tcl_PkgProvide (interp, "Gt_lsd_tree_layout_walker", version);
    if (code != TCL_OK) {
	return code;
    }

    return code;
}
