#include <stdlib.h>
#include "stack-c.h"
#include "api_scilab.h"
#include "Scierror.h"
#include "sciprint.h"
#include "string.h"

#include "CellTree.h"
#include "Erreur.h"

/***************************************
 * SCILAB function : CreateCellTree    *
 ***************************************/

int gtw_CreateCellTree ( char * fname )
{
    int m,n,l;
	int HandleFlowDir;
    int HandleTree;
    int RootCell;
    int un=1;

    CheckRhs(2,2);
    CheckLhs(1,1);
    
    /* Variable HandleFlowDir */

    GetRhsVar(1,"i",&m,&n,&l);
    CheckScalar(1,m,n);
    HandleFlowDir = *istk(l);

    /* Variable RootCell */

    GetRhsVar(2,"i",&m,&n,&l);
    CheckScalar(2,m,n);
    RootCell = *istk(l);
	
	/* Appel à l'API */

	HandleTree = CreateCellTree ( 	HandleFlowDir, RootCell );

	if ( HandleTree < 0 ) Scierror (999, GetErreur());
	
	/* Variable HandleTree */
	
	CreateVar(Rhs + 1,"i",&un,&un,&l);
	*istk(l) = HandleTree ;
	LhsVar(1) = Rhs + 1 ;

	return(0);
}

/***********************************************
 * SCILAB function : CreateWeightedCellTree    *
 ***********************************************/

int gtw_CreateWeightedCellTree ( char * fname )
{
    int m,n,l;
	int HandleFlowDir;
    int HandleTree;
	int HandleWeight;
    int RootCell;
    int un=1;

    CheckRhs(3,3);
    CheckLhs(1,1);
    
    /* Variable HandleFlowDir */

    GetRhsVar(1,"i",&m,&n,&l);
    CheckScalar(1,m,n);
    HandleFlowDir = *istk(l);

    /* Variable RootCell */

    GetRhsVar(2,"i",&m,&n,&l);
    CheckScalar(2,m,n);
    RootCell = *istk(l);
	
    /* Variable HandleWeight */

    GetRhsVar(3,"i",&m,&n,&l);
    CheckScalar(3,m,n);
    HandleWeight = *istk(l);

	/* Appel à l'API */

	HandleTree = CreateWeightedCellTree ( 	HandleFlowDir, RootCell, HandleWeight);

	if ( HandleTree < 0 ) Scierror (999, GetErreur());
	
	/* Variable HandleTree */
	
	CreateVar(Rhs + 1,"i",&un,&un,&l);
	*istk(l) = HandleTree ;
	LhsVar(1) = Rhs + 1 ;

	return(0);
}

/***************************************
 * SCILAB function : DestroyCellTree   *
 ***************************************/

int gtw_DestroyCellTree ( char * fname )
{
	int HandleTree;
	int m, n, l;

	CheckRhs(1,1);
	CheckLhs(0,1);

	/* Variable HandleTree */

	GetRhsVar(1,"i",&m,&n,&l);
	CheckScalar(1, m, n);
	HandleTree = *istk(l);

	if (DestroyCellTree(HandleTree)) Scierror(999,GetErreur());

	return(0);
}


/**********************************************
 * SCILAB function : sci_CreateCellTree_iter  *
 **********************************************/

int gtw_CreateCellTree_iter ( char * fname )
{
    int m,n,l;
    int HandleFlowDir, HandleWeight, HandleTree;
    int RootCell;
    int un=1;

    CheckRhs(3,3);
    CheckLhs(1,1);
    
    /* Variable HandleFlowDir */

    GetRhsVar(1,"i",&m,&n,&l);
    CheckScalar(1,m,n);
    HandleFlowDir = *istk(l);

    /* Variable RootCell */

    GetRhsVar(2,"i",&m,&n,&l);
    CheckScalar(2,m,n);
    RootCell = *istk(l);
	
    /* Variable HandleWeight */

    GetRhsVar(3,"i",&m,&n,&l);
    CheckScalar(3,m,n);
    HandleWeight = *istk(l);
	
	/* Appel à l'API */

	HandleTree = CreateCellTree_iter ( HandleFlowDir, RootCell, HandleWeight );

	if ( HandleTree < 0 ) Scierror (999, GetErreur());
	
	/* Variable HandleTree */
	
	CreateVar(Rhs + 1,"i",&un,&un,&l);
	*istk(l) = HandleTree ;
	LhsVar(1) = Rhs + 1 ;

	return(0);
}

/***************************************
 * SCILAB function : MakeStreamLines   *
 ***************************************/

int gtw_MakeStreamLines ( char * fname )
{
    int m,n,l,l_mlist,i;
    int HandleTree;
    float threshold ;
	int todivide;
    int ** StreamCells ;
	int ** StreamConnect ;
	int * StreamLength;
	int nstreams;
    int un=1;
	char ** Labels;

    CheckRhs(3,3);
    CheckLhs(3,3);
		
    /* Variable HandleTree */

    GetRhsVar(1,"i",&m,&n,&l);
    CheckScalar(1,m,n);
    HandleTree = *istk(l);

    /* Variable threshold */

    GetRhsVar(2,"r",&m,&n,&l);
    CheckScalar(2,m,n);
    threshold = *sstk(l);

	/* Variable todivide */

    GetRhsVar(3,"i",&m,&n,&l);
    CheckScalar(3,m,n);
    todivide = *istk(l);
	
    /* Appel a l'API */
	
	StreamConnect = (int **) malloc ( 2 * sizeof (int *) );

    if ( MakeStreamLines ( HandleTree , & threshold , & todivide , & nstreams , & StreamLength , & StreamConnect , & StreamCells ) )
        Scierror (999, GetErreur());
	
	// Création des labels
	
	m = nstreams + 1;
	
	if ( !(Labels = (char **) malloc ( m * sizeof(char *) ) ) )
		Scierror (999, "gtw_MakeStreamLines : echec de l'allocation des chaines de caracteres\n");
	
	Labels[0] = (char *) malloc ( 4 * sizeof(char) );
	strncpy (Labels[0],"Type",4);
	
	for(i=0;i<nstreams;i++)
	{
		Labels[i+1] = (char *) malloc ( 6 * sizeof(char) );
		strncpy (Labels[i+1],"Stream",6);
	}
	
	// Création d'un object de type mlist
	
	CreateVar ( Rhs + 1 , "m", & m, & un , & l );	

	// Affectation des labels
	
	CreateListVarFromPtr ( Rhs + 1 ,  1 , "S" , & m , & un , Labels );
	
	// Création des composantes de la liste
	
	for (i=0;i<nstreams;i++)
	{
		CreateListVarFromPtr ( Rhs + 1 ,  i + 2 , "i" , & StreamLength[i] , & un , & StreamCells[i] );
		free(StreamCells[i]);
	}

	/* Création des tableaux de connections entre les lignes d'écoulement */
	
	CreateVarFromPtr ( Rhs + 2 ,  "i", & nstreams , & un , & StreamConnect[0] );
	CreateVarFromPtr ( Rhs + 3 ,  "i", & nstreams , & un , & StreamConnect[1] );
		
	/* Affectation des sorties */
	
    LhsVar(1) = Rhs + 1;
	LhsVar(2) = Rhs + 2;
	LhsVar(3) = Rhs + 3;

	/* Désaffectation des pointeurs */
	
    free(StreamLength);
	free(StreamCells);
	free(StreamConnect[0]);
	free(StreamConnect[1]);
	free(StreamConnect);

    return(0);
}

/***************************************
 * SCILAB function : SampleMainStream  *
 ***************************************/

int gtw_SampleMainStream ( char * fname )
{

    int m,n,l;
    int HandleTree;
    int * TributOutlet ;
	int * TributSize ;
	int ntribut;
    int un=1;

    CheckRhs(1,1);
    CheckLhs(1,2);
		
	/* Variable HandleTree */

    GetRhsVar(1,"i",&m,&n,&l);
    CheckScalar(1,m,n);
    HandleTree = *istk(l);

	/* Appel a l'API */
	
	if ( SampleMainStream ( HandleTree , & ntribut , & TributOutlet , & TributSize ) )
        Scierror (999, GetErreur());

	CreateVarFromPtr ( Rhs + 1 ,  "i", & ntribut , & un , & TributOutlet );
	CreateVarFromPtr ( Rhs + 2 ,  "i", & ntribut , & un , & TributSize );
	
	/* Affectation des sorties */
	
    LhsVar(1) = Rhs + 1;
	LhsVar(2) = Rhs + 2;

	free(TributOutlet);
	free(TributSize);
	
	return(0);
}


/********************************************
 * SCILAB function : MainBifurcationNode    *
 ********************************************/

int gtw_MainBifurcationNode ( char * fname )
{
	int m, n, l;
        int HandleTree;
		int un = 1;
        int quatre = 4;
        int * ABCD;
        
        CheckRhs(1,1);
		CheckLhs(1,1);

	/* Variable HandleTree */
	
        GetRhsVar(1,"i",&m,&n,&l);
		CheckScalar(1,m,n);
        HandleTree = *istk(l);

        /* Allocation des tableaux de sortie */

        ABCD = (int *)malloc(4*sizeof(int));
        
        if ( MainBifurcationNode ( HandleTree , ABCD , ABCD+1 , ABCD+2 , ABCD+3 ) )
            Scierror(999,GetErreur());

        /* Création des tableaux de sortie sur le stack */

        CreateVarFromPtr ( Rhs + 1 , "i", & un , & quatre , & ABCD );
		LhsVar(1) = Rhs + 1;

        free(ABCD);

        return(0);
}

/********************************************
 * SCILAB function : UpstreamAverage        *
 ********************************************/

int gtw_UpstreamAverage ( char * fname )
{
	int m, n, l;
    int HandleTree,HandleRasterLocal,HandleRasterAveraged;
	int un = 1;
        
    CheckRhs(3,3);
	CheckLhs(0,1);

	/* Variable HandleTree */
	
    GetRhsVar(1,"i",&m,&n,&l);
	CheckScalar(1,m,n);
    HandleTree = *istk(l);
    
	/* Variable HandleRasterLocal */
	
    GetRhsVar(2,"i",&m,&n,&l);
	CheckScalar(2,m,n);
    HandleRasterLocal = *istk(l);
	
	/* Variable HandleRasterAveraged */
	
    GetRhsVar(3,"i",&m,&n,&l);
	CheckScalar(3,m,n);
    HandleRasterAveraged = *istk(l);
    
    if ( UpstreamAverage ( HandleTree , HandleRasterLocal,HandleRasterAveraged ) )
            Scierror(999,GetErreur());

    return(0);
}

