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

#include "FlowDirGrid.h"
#include "Topology.h"
#include "FloatRaster.h"
#include "RasterCalc.h"
#include "Erreur.h"

/********************************************
 * SCILAB function : GetCatchmentSize       *
 ********************************************/

int gtw_GetCatchmentSize ( char * fname )
{
	int m, n, l;
	int un = 1;
    int HandleFlowDir,cell,nup,nupnodes,nixupnodes;
	int * UPNODES , * IXUPNODES ;
	int	* BB;
	int bbsize = 4;
	
	CheckRhs(3,3);
	CheckLhs(3,3);

	/* Variable HandleFlowDir */

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

	/* Variable cell */

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

	GetRhsVar(3,"i",&m,&n,&l);
	nupnodes = m*n;
    UPNODES = istk(l);
	
	BB = (int *) malloc ( bbsize * sizeof(int) );
	
        /* Appel a l'API */

        if ( GetCatchmentSize ( HandleFlowDir , cell , nupnodes , UPNODES , & BB , & nup , & IXUPNODES , & nixupnodes ) )
            Scierror(999,GetErreur());

    CreateVar(Rhs + 1,"i",&un,&un,&l);
	*istk(l) = nup ;
	LhsVar(1) = Rhs +1 ;

    CreateVarFromPtr ( Rhs + 2 , "i", & un , & bbsize , & BB );
	LhsVar(2) = Rhs + 2;

	CreateVarFromPtr ( Rhs + 3 , "i", & un , & nixupnodes , & IXUPNODES );
	LhsVar(3) = Rhs + 3;
	
	free(IXUPNODES);
	free(BB);
	FreePtr(UPNODES);
	
    return(0);
}

/********************************************
 * SCILAB function : GetCatchmentCells      *
 ********************************************/

int gtw_GetCatchmentCells ( char * fname )
{
	int m, n, l;
	int one = 1;
	int nbb = 4;
    int HandleFlowDir,cell,nup,ninlets,nselinlets;
    int * CATCHMENT, * INLETS , * SELINLETS ;
	int * bb;
	
	CheckRhs(3,3);
	CheckLhs(3,3);

	/* Variable HandleFlowDir */

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

	/* Variable cell */

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

	GetRhsVar(3,"i",&m,&n,&l);
	ninlets = m*n;
    INLETS = istk(l);
		
	bb = (int *)malloc(nbb*sizeof(int));
	
        /* Appel a l'API */

        if ( GetCatchmentCells ( HandleFlowDir , cell , INLETS , ninlets , & nup , & CATCHMENT , & bb , & SELINLETS , & nselinlets ) )
            Scierror(999,GetErreur());

        CreateVarFromPtr ( Rhs + 1 , "i", & nup , & one , & CATCHMENT );
		LhsVar(1) = Rhs + 1;
		
	    CreateVarFromPtr ( Rhs + 2 , "i", & one , & nbb , & bb );
		LhsVar(2) = Rhs + 2;
		
        CreateVarFromPtr ( Rhs + 3 , "i", & nselinlets , & one , & SELINLETS );
		LhsVar(3) = Rhs + 3;
        
		free(bb);
		free(INLETS);
		free(CATCHMENT);

        return(0);
}


/********************************************
 * SCILAB function : MakeDistanceMap        *
 ********************************************/

int gtw_MakeDistanceMap ( char * fname )
{
    int m, n, l;
    int HandleFlowDir,HandleMap,outlet;

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

    /* Variable HandleFlowDir */

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

    /* Variable HandleMap */

    GetRhsVar(2,"i",&m,&n,&l);
    CheckScalar(2,m,n);
    HandleMap = *istk(l);

    /* Variable outlet */

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

    if ( MakeDistanceMap ( HandleFlowDir, HandleMap, outlet ) )
        Scierror(999,GetErreur());

    return(0);
}

/************************************************
 * SCILAB function : sci_MakeDistanceMap_iter   *
 ************************************************/

int gtw_MakeDistanceMap_iter ( char * fname )
{
    int m, n, l;
    int HandleFlowDir,HandleMap,outlet;

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

    /* Variable HandleFlowDir */

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

    /* Variable HandleMap */

    GetRhsVar(2,"i",&m,&n,&l);
    CheckScalar(2,m,n);
    HandleMap = *istk(l);

    /* Variable outlet */

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

    if ( MakeDistanceMap_iter ( HandleFlowDir, HandleMap, outlet ) )
        Scierror(999,GetErreur());

    return(0);
}

/********************************************
 * SCILAB function : MakeAccumulationMap    *
 ********************************************/

int gtw_MakeAccumulationMap ( char * fname )
{
    int m, n, l;
    int HandleFlowDir,HandleMap;

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

    /* Variable HandleFlowDir */

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

    /* Variable HandleMap */

    GetRhsVar(2,"i",&m,&n,&l);
    CheckScalar(2,m,n);
    HandleMap = *istk(l);

    if ( MakeAccumulationMap ( HandleFlowDir, HandleMap ) )
        Scierror(999,GetErreur());

    return(0);
}

/********************************************
 * SCILAB function : GetDowstreamSet        *
 ********************************************/

int gtw_GetDownstreamSet ( char * fname )
{
    int m, n, l;
    int HandleFlowDir,ncells;
    int * CELLS , * DOWNSTREAM;

    CheckRhs(2,2);
    CheckLhs(1,1);

    /* Variable HandleFlowDir */

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

    /* Variable CELLS */

    GetRhsVar(2,"i",&m,&n,&l);
    CELLS = istk(l);

    ncells = m*n;

    if( !(DOWNSTREAM = (int *) malloc(ncells*sizeof(int)) ) )
        Scierror(999,"gtw_GetDowstreamSet : echec de l'allocation dans l'interface\n");

    /* Appel Ã  l'API */

    if ( GetDownstreamSet ( HandleFlowDir , ncells , CELLS , & DOWNSTREAM ) )
        Scierror(999,GetErreur());

    /* CrÃ©ation de la variable DOWNSTREAM sur le stack */

    CreateVarFromPtr ( Rhs + 1 , "i", & m, & n , & DOWNSTREAM );
    LhsVar(1) = Rhs + 1;

    free(DOWNSTREAM);

    return(0);
}

/********************************************
 * SCILAB function : CropRasterToCatchment  *
 ********************************************/
/*
int gtw_CropRasterToCatchment ( char * fname )
{
	int m, n, l;
	int un = 1;
	int quatre = 4;
    int HandleFlowDir,cell,nup,ncols,nrows,LL;
    int HandleRaster,ncols1,nrows1,LL1;
	double cellsize,xll,yll,cellsize1,xll1,yll1;
	float NODATA_value,NODATA_value1;
	int nr,nc,nr1,nc1,rec,i,roffset,coffset;
	float code;
    int * CATCHMENT , * bb ;
	float * CODE;
	char * Nom;

	CheckRhs(4,4);
	CheckLhs(1,1);

	// Variable Nom

	GetRhsVar(1,"c",&m,&n,&l);
	Nom = cstk(l);

	// Variable HandleFlowDir

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

	// Variable cell

	GetRhsVar(3,"i",&m,&n,&l);
	CheckScalar(3,m,n);
    cell = *istk(l);
	
	// Variable code

	GetRhsVar(4,"r",&m,&n,&l);
	CheckScalar(4,m,n);
    code = *sstk(l);
	
	bb = (int *)malloc(4*sizeof(int));
	
        // API : Récupération du header
        
		if ( GetFlowDirGridHeader ( HandleFlowDir ,
                                    & ncols ,
                                    & nrows ,
                                    & cellsize ,
                                    & xll ,
                                    & yll ,
                                    & NODATA_value ,
                                    & LL ) )
            Scierror(999,GetErreur());	

		// API : Récupération des cellules du BV
		
        if ( GetCatchmentCells ( HandleFlowDir , & cell , & nup , & CATCHMENT , & bb ) )
            Scierror(999,GetErreur());

		// API : Création du nouveau raster

		ncols1 = bb[1]-bb[0]+1;
		nrows1 = bb[3]-bb[2]+1;
		cellsize1 = cellsize;
		LL1 = LL;
		NODATA_value1 = NODATA_value;
		coffset = bb[0];		
		roffset = nrows-1-bb[3];
		xll1 = xll + ((double)coffset)*cellsize1;
		yll1 = yll + ((double)roffset)*cellsize1;
		
		HandleRaster = CreateFloatRaster ( 	Nom,
						ncols1,
						nrows1,
						cellsize1,
						xll1,
						yll1,
						NODATA_value1,
						LL
					);

		if ( HandleRaster < 0 ) Scierror (999, GetErreur());
		
		// API : initialisation du raster
		
		if ( SetRasterToNODATA ( HandleRaster ) )
            Scierror(999,GetErreur());
			
		// Renumérotation des cellules à marquer dans le nouveau raster
		
		if( !(CODE = (float *) malloc(nup*sizeof(float))) )
            Scierror(999,"%s : echec de l allocation du bloc de donnees CODE\n",fname);
		
		for(i=0;i<nup;i++)
		{
			rec = CATCHMENT[i];
			nc = rec % ncols;
			nr = (rec-nc)/ncols;
			
			nc1 = nc-bb[0];
			nr1 = nr-bb[2];
			CATCHMENT[i] = nc1+nr1*ncols1;
			
			CODE[i] = code;
		}
		
		// Marquage des cellules du BV dans le nouveau raster
		
		if( PutRasterValue ( HandleRaster, nup, CATCHMENT, CODE ) )
            Scierror(999,GetErreur());
		
		// Création du handle du nouveau raster stack 
		
    CreateVar(Rhs + 1,"i",&un,&un,&l);
	*istk(l) = HandleRaster ;
	LhsVar(1) = Rhs +1 ;
	
		free(bb);
		free(CATCHMENT);
		free(CODE);
		
        return(0);
}
*/
/********************************************
 * SCILAB function : MakeFlowLine           *
 ********************************************/

int gtw_MakeFlowLine ( char * fname )
{
    int m, n, l;
    int HandleFlowDir,A,B;
    int * FLOWLINE;
	int length;
	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 A */

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

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

	FLOWLINE = NULL;
	
    /* Appel Ã  l'API */

    if ( MakeFlowLine ( HandleFlowDir , A , B , & FLOWLINE , & length ) )
        Scierror(999,GetErreur());

    /* CrÃ©ation de la variable FLOWLINE sur le stack */

    CreateVarFromPtr ( Rhs + 1 , "i", & length , & un , & FLOWLINE );
    LhsVar(1) = Rhs + 1;

    free(FLOWLINE);

    return(0);
}

/****************************************
 * SCILAB function : MakeArcs           *
 ****************************************/

int gtw_MakeArcs ( char * fname )
{
    int m, n, l;
    int HandleFlowDir,nnodes,narcs;
    int * NODES , * UP , * DOWN ;
	int un=1;

    CheckRhs(2,2);
    CheckLhs(2,2);

    /* Variable HandleFlowDir */

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

    /* Variable NODES */

    GetRhsVar(2,"i",&m,&n,&l);
    NODES = istk(l);

    nnodes = m*n;

    UP = NULL ;
	DOWN = NULL ;
	
    /* Appel à l'API */

    if ( MakeArcs ( HandleFlowDir , NODES , nnodes , & UP , & DOWN , & narcs ) )
        Scierror(999,GetErreur());

    /* Création de la variable ARCS sur le stack, matrice [narcs,2] */

    CreateVarFromPtr ( Rhs + 1 , "i", & narcs , & un , & UP );
    LhsVar(1) = Rhs + 1;

    CreateVarFromPtr ( Rhs + 2 , "i", & narcs , & un , & DOWN );
    LhsVar(2) = Rhs + 2;
	
	free(UP);
	free(DOWN);
	
    return(0);
}

/****************************************
 * SCILAB function : GetDownstreamPath  *
 ****************************************/
 
int gtw_GetDownstreamPath  ( char * fname )
{
    int m, n, l;
    int HandleFlowDir,length,start;
    int * FLOWLINE ;
	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 start */

    GetRhsVar(2,"i",&m,&n,&l);
    start = *istk(l);

	FLOWLINE = NULL ;
	
    /* Appel à l'API */

    if ( GetDownstreamPath  ( HandleFlowDir , start , & FLOWLINE , & length ) )
        Scierror(999,GetErreur());

    
    CreateVarFromPtr ( Rhs + 1 , "i", & length , & un , & FLOWLINE );
    LhsVar(1) = Rhs + 1;

	free(FLOWLINE);
	
    return(0);
}







