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

#include "FlowDirGrid.h"
#include "Erreur.h"

/********************************************
 * SCILAB function : CreateFlowDirGrid       *
 ********************************************/

int gtw_CreateFlowDirGrid ( char * fname )
{
	char * Nom;
	
	int m, n, l;
	int un = 1;
    int nrows,ncols,LL,HandleFlowDir;
    double cellsize,xll,yll;
	float NODATA_value;

	CheckRhs(8,8);
	CheckLhs(1,1);

	/* Variable Nom */

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

	/* Variable ncols */

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

	/* Variable nrows */

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

	/* Variable cellsize */

	GetRhsVar(4,"d",&m,&n,&l);
	CheckScalar(4,m,n);
	cellsize = *stk(l);

	/* Variable xll */

	GetRhsVar(5,"d",&m,&n,&l);
	CheckScalar(5,m,n);
	xll = *stk(l);

	/* Variable yll */

	GetRhsVar(6,"d",&m,&n,&l);
	CheckScalar(6,m,n);
	yll = *stk(l);

	/* Variable NODATA_value */

	GetRhsVar(7,"r",&m,&n,&l);
	CheckScalar(7,m,n);
	NODATA_value = *sstk(l);

	/* Variable LL */

	GetRhsVar(8,"i",&m,&n,&l);
	CheckScalar(8,m,n);
	NODATA_value = *istk(l);

	/* Appel � l'API */

	HandleFlowDir = CreateFlowDirGrid ( 	Nom,
						ncols,
						nrows,
						cellsize,
						xll,
						yll,
						NODATA_value,
						LL
					);

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

	return(0);
}

/********************************************
 * SCILAB function : DestroyFlowDirGrid    *
 ********************************************/

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

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

	/* Variable HandleFlowDir */

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

	if (DestroyFlowDirGrid(HandleFlowDir)) Scierror(999,GetErreur());

	return(0);
}

/********************************************
 * SCILAB function : CreateFlowDirGridFromBinaryFile    *
 ********************************************/

int gtw_CreateFlowDirGridFromBinaryFile ( char * fname )
{
    	char * Nom , * binfile , * hdrfile ;

	int m, n, l,i;
	int un = 1;
    int TYPE_SRC,HandleFlowDir;
    double * Compass_d ;
    float Compass[3][3];

	CheckRhs(5,5);
	CheckLhs(1,1);

	/* Variable Nom */

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

        /* Variable binfile */

        GetRhsVar(2,"c",&m,&n,&l);
	binfile = cstk(l);

        /* Variable hdrfile */

        GetRhsVar(3,"c",&m,&n,&l);
	hdrfile = cstk(l);

        /* Variable TYPE_SRC */

        GetRhsVar(4,"i",&m,&n,&l);
        CheckScalar(4,m,n);
        TYPE_SRC = *istk(l);

        /* Variable Compass_d */

        GetRhsVar(5,"d",&m,&n,&l);
        CheckDimProp(5,5, m != 3);
        CheckDimProp(5,5, n != 3);
        Compass_d = stk(l);
        
        /* Conversion en float et transposition de la matrice Compass */
        
        i=0;

        for(n=0;n<3;n++)
        {
            for(m=0;m<3;m++)
            {
                Compass[m][n] = (float)(Compass_d[i]);
                i++;
            }
        }

        /* Appel � l'API */

	HandleFlowDir = CreateFlowDirGridFromBinaryFile ( 	Nom,
                                                                binfile,
                                                                hdrfile,
                                                                TYPE_SRC,
                                                                Compass
                                                         );

	if ( HandleFlowDir < 0 ) Scierror (999, GetErreur());

	/* Variable HandleFlowDir */

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

	return(0);
}

int gtw_GetFlowDirGridHeader ( char * fname )
{
	int HandleFlowDir;
	int m, n, l;
    int ncols,nrows,LL;
    double cellsize,xll,yll;
	float NODATA_value;
    int headerlength=7;
    int un=1;

    double * Header;

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

	/* Variable HandleFlowDir */

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

        if ( GetFlowDirGridHeader ( HandleFlowDir ,
                                    & ncols ,
                                    & nrows ,
                                    & cellsize ,
                                    & xll ,
                                    & yll ,
                                    & NODATA_value ,
                                    & LL ) )
            Scierror(999,GetErreur());
		
		Header = (double *)malloc(headerlength*sizeof(double));	
			
        Header[0] = (double)ncols;
        Header[1] = (double)nrows;
        Header[2] = cellsize;
        Header[3] = xll;
        Header[4] = yll;
        Header[5] = (double)NODATA_value;
        Header[6] = (double)LL;

        CreateVarFromPtr ( Rhs + 1 , "d", & headerlength, & un, & Header );
	LhsVar(1) = Rhs + 1;

		free(Header);
	
        return(0);
}

/*
int gtw_GetFlowDirGridData ( char * fname )
{
	int HandleFlowDir;
	int m, n, l;
        int ncols,nrows,LL;
        float cellsize,xll,yll,NODATA_value;
        int sept=7;
        int un=1;

        float * Header;
        unsigned char * Data;

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

	// Variable HandleFlowDir

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

        if ( GetFlowDirGridHeader ( HandleFlowDir ,
                                    & ncols ,
                                    & nrows ,
                                    & cellsize ,
                                    & xll ,
                                    & yll ,
                                    & NODATA_value ,
                                    & LL ) )
            Scierror(999,GetErreur());

        Header = (float *)malloc(7*sizeof(float));

        Header[0] = (float)ncols;
        Header[1] = (float)nrows;
        Header[2] = (float)cellsize;
        Header[3] = (float)xll;
        Header[4] = (float)yll;
        Header[5] = (float)NODATA_value;
        Header[6] = (float)LL;

        // Dimensionnement du tableau contenant les données

        if( !(Data = (unsigned char *) malloc(nrows*ncols*sizeof(unsigned char))) )
            Scierror(999,"%s : echec de l allocation du bloc de donnees\n",fname);

        if ( GetFlowDirGridData ( HandleFlowDir , & Data ) )
                    Scierror(999,GetErreur());

        CreateVarFromPtr ( Rhs + 1 , "c", & nrows, & ncols, & Data );
	LhsVar(1) = Rhs + 1;

//        CreateVarFromPtr ( Rhs + 2 , "r", & sept, & un, & Header );
//	LhsVar(2) = Rhs + 2;

        free(Header);
        free(Data);

        return(0);
}
*/


/********************************************************
 * SCILAB function : WriteFlowDirToFile                 *
 ********************************************************/

int gtw_WriteFlowDirToFile (   char * fname )
{
    	char * binfile;
		int m, n, l;
        int TYPE_DST,HandleFlowDir,SWITCH_ENDIANNESS;

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

	/* Variable HandleFlowDir */

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

        /* Variable binfile */

        GetRhsVar(2,"c",&m,&n,&l);
		binfile = cstk(l);

        /* Variable TYPE_DST */

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

        /* Variable SWITCH_ENDIANNESS */

        GetRhsVar(4,"i",&m,&n,&l);
        CheckScalar(4,m,n);
        SWITCH_ENDIANNESS = *istk(l);

        /* Appel a l'API */

        if ( WriteFlowDirGridToFile ( HandleFlowDir, binfile, TYPE_DST, SWITCH_ENDIANNESS) )
            Scierror(999,GetErreur());

	return(0);
}

/*******************************************************
 * SCILAB function : PutFlowDirValue                   *
 *******************************************************/

int gtw_PutFlowDirValue  (   char * fname )
{

    	char * binfile;
		int m, n, l , mc,nc,mv,nv,ncells,i ;
        int HandleFlowDir;
        double * Compass_d ;
		int * CELLS ; 
		float * VALUES ;
        float Compass[3][3];
		
		CheckRhs(4,4);
		CheckLhs(0,1);

		/* Variable HandleFlowDir */

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

        /* Variable CELLS */

		GetRhsVar(2,"i",&mc,&nc,&l);
		CELLS = istk(l);
		ncells = mc*nc;

        /* Variable VALUES */

		GetRhsVar(3,"r",&mv,&nv,&l);
        CheckDimProp(2,3,mc!=mv);
        CheckDimProp(2,3,nc!=nv);
        VALUES = sstk(l);

        /* Variable Compass_d */

        GetRhsVar(4,"d",&m,&n,&l);
        CheckDimProp(4,4, m != 3);
        CheckDimProp(4,4, n != 3);
        Compass_d = stk(l);
        
        /* Conversion en float et transposition de la matrice Compass */
        
        i=0;

        for(n=0;n<3;n++)
        {
            for(m=0;m<3;m++)
            {
                Compass[m][n] = (float)(Compass_d[i]);
                i++;
            }
        }

        /* Appel a l'API */

        if ( PutFlowDirValue ( 	HandleFlowDir , ncells , CELLS , VALUES, Compass ) )
				Scierror(999,GetErreur());

	return(0);
}


/*******************************************************
 * SCILAB function : GetFlowDirValue                   *
 *******************************************************/

int gtw_GetFlowDirValue  (   char * fname )
{

    	char * binfile;
		int m, n, l , mc,nc,mv,nv,ncells,i ;
        int HandleFlowDir;
        double * Compass_d ;
		int * CELLS ; 
		float * VALUES ;
        float Compass[3][3];
		
		CheckRhs(3,3);
		CheckLhs(1,1);

		/* Variable HandleFlowDir */

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

        /* Variable CELLS */

		GetRhsVar(2,"i",&mc,&nc,&l);
		CELLS = istk(l);
		ncells = mc*nc;

        /* Variable Compass_d */

        GetRhsVar(3,"d",&m,&n,&l);
        CheckDimProp(3,3, m != 3);
        CheckDimProp(3,3, n != 3);
        Compass_d = stk(l);
        
        /* Conversion en float et transposition de la matrice Compass */
        
        i=0;

        for(n=0;n<3;n++)
        {
            for(m=0;m<3;m++)
            {
                Compass[m][n] = (float)(Compass_d[i]);
                i++;
            }
        }

		if( !(VALUES = (float *) malloc(ncells*sizeof(float)) ) )
        Scierror(999,"gtw_GetFlowDirValue : echec de l'allocation dans l'interface\n");
		
        /* Appel a l'API */

        if ( GetFlowDirValue ( 	HandleFlowDir , ncells , CELLS , Compass , & VALUES ) )
				Scierror(999,GetErreur());
				
	    /* CrÃƒÂ©ation de la variable VALUES sur le stack */

    CreateVarFromPtr ( Rhs + 1 , "r", & mc, & nc , & VALUES );
    LhsVar(1) = Rhs + 1;

    free(VALUES);

    return(0);

}

/********************************************************
 * SCILAB function : sci_CropFlowDir                    *
 ********************************************************/

int gtw_CropFlowDir (   char * fname )
{
	char * Nom ;
    int m, n, l;
	int un = 1;
	int startrow, startcol, endrow, endcol ;
    int HandleFlowDir,HandleCroppedFlowDir ;

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

	/* Variable HandleFlowDir */

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

    /* Variable startrow */

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

    /* Variable startcol */

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

    /* Variable endrow */

    GetRhsVar(4,"i",&m,&n,&l);
	CheckScalar(4,m,n);
	endrow = *istk(l);

    /* Variable endcol */

    GetRhsVar(5,"i",&m,&n,&l);
	CheckScalar(5,m,n);
	endcol = *istk(l);	
	
	/* Variable Nom */

	GetRhsVar(6,"c",&m,&n,&l);
	Nom = cstk(l);
	
    /* Appel a l'API */

	HandleCroppedFlowDir = CropFlowDir ( HandleFlowDir , startrow , startcol , endrow , endcol , Nom ) ;
	
    if ( HandleCroppedFlowDir < 0 )
		Scierror(999,GetErreur());

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

	return(0);
}


/********************************************************
 * SCILAB function : SetFlowDirToNoFlow                 *
 ********************************************************/

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

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

	/* Variable HandleFlowDir */

	GetRhsVar(1,"i",&m,&n,&l);
	HandleFlowDir = *istk(l);
	
	if ( SetFlowDirToNoFlow ( HandleFlowDir ) )
		Scierror(999,GetErreur());
	
	return(0);
}