#ifndef HEADER_SCHEMAGAMEGENERATOR
#define HEADER_SCHEMAGAMEGENERATOR

/**
 * @file 
 * File containing the interface of schemaGameGenerator module
 */

#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#include "define.h"


/* Start interface of schemaGameGenerator module */


/** Data struct containing coordinates data type.*/
struct coordinates_data
{
    unsigned int row;   /**< Row (X)*/
    unsigned int col;   /**< Columns (Y)*/
};

/* Definition of the type coordinates_data.*/
typedef struct coordinates_data coordinates;

/** Data struct containing directions data type.*/
struct possible_directions
{
        unsigned int left;  /**< Left (X-1)*/
        unsigned int right; /**< Right (X+1)*/
        unsigned int up;    /**< Up (Y-1)*/
        unsigned int down;  /**< Down (Y+1)*/
};

/* Definition of the type possible_directions.*/
typedef struct possible_directions directions;



/** Create a new schema with dimension Row x Column and 
    pre-determinate difficult in given file.
    Steps :
    - Check the parameters
    - Put a start point
    - Generate dx and dy (deny areas)
    - Choose the number of doors    
    - Put the doors 
    - Generate the routes
    - Open/Close blocks to increase difficult
    - Create the file

   @return Positive value (true) if no errors occours in the function execution
           Negative value (false) otherwise.
*/
bool generateSchema( const char *filename,   /**< File name*/
                     unsigned int numRow,    /**< Rows number*/
                     unsigned int numCol,    /**< Columns number*/
                     unsigned int difficult  /**< Difficult level*/
                   );


/** Check the pre-conditions to run the 
    generateSchema function well.
    @return Positive value (true) if no errors 
            occours in the function execution
            Negative value (false) otherwise.
*/
bool check_generateSchema( const FILE *newSchemaFile, /**< File to save
                                                           the game */
                           unsigned int difficult,   /**< Difficult level */
                           unsigned int numRow,      /**< Number of row */
                           unsigned int numCol       /**< Number of column */
                         );


/** Dynamic map allocation with row dimension
    as numRow and column dimension al numCol.
    @return a pointer to matrix
*/
char **gameMap_alloc_and_set( unsigned int numRow, /**< Number of row */
                              unsigned int numCol  /**< Number of column */
                            );


/** After start point creation, this function uses ::getRouteNumber , 
    ::get_denyArea , ::get_available_cells , ::point_in_random_direction , 
    ::getRouteNumber , ::get_MaxRouteLen and ::get_direction_from_point 
    functions to generate some routes from the calculate start point to 
    the calculate doors.
    @return function execution time
    */
double create_routes( unsigned int difficult,/**< Difficult level */
                      unsigned int numRow,/**< Number of row */
                      unsigned int numCol,/**< Number of column */
                      char **gameMap/**< Schema game map */
                    );
                         

/** Find a length, starting from start direction ( X or Y ),
    where a DOOR could not stay. This measure maybe variable
    and this variability maybe obtained by random function.
    This value is attenuate using difficult percentage.
    @return number of deny cells from start direction
*/
unsigned int get_denyArea( unsigned int difficult, /**< Difficult level */
                           unsigned int numDir,    /**< Number in that Dir-
                                                        ection Eg. Dir = Row */
                           unsigned int startDir   /**< Start position Dir-
                                                        ection Eg. Dir = Col */
                         );


/** Find the appropriate number of routes for a schema
    having (row,column) dimensions as (numRow,numCol).
    This measure maybe variable and this variability 
    maybe obtained by random function.
    This value is attenuate using difficult percentage.
    @return number of deny cells from start direction
*/
unsigned int getRouteNumber( unsigned int difficult,/**< Difficult level */
                             unsigned int numRow,   /**< Number of row */
                             unsigned int numCol    /**< Number of column */
                           );


/** Set the number of available cells in all possible directions.
    @return number of available cells in structure directions.
*/
directions set_number_of_available_cells( coordinates start,  /**< Start 
                                                                 coordinates.*/
                                          coordinates deny,   /**< Deny area 
                                                                coordinates*/
                                          unsigned int numRow,/**< Number of 
                                                                   row */
                                          unsigned int numCol /**< Number of 
                                                                   column */
                                        );


/** Extimate the maximum route lenght to reach the door 
   (with coordinates (doorX,doorY) ), starting from
   start point (with coordinates (startRow,startCol) ),
   in a schema with dimensions (numRow,numCol).
   @return maximum route length from start point to the door
*/
unsigned int get_MaxRouteLen( unsigned int numRow, /**< Number of row */
                              unsigned int numCol, /**< Number of column */
                              coordinates start,   /**< Start coordinates */
                              coordinates door     /**< Door cooridnates */
                            );
                         

/** Calculate, using also random function, the value of specified coordinate
    of a point in the available area, and set the relative probability.
    @return Coordinate value.
*/
unsigned int point_in_random_direction(
 
                               unsigned int avail_dir1, /**< Number of available 
                                                             cells in direction 
                                                             'dir1' Eg. left */
                               unsigned int avail_dir2, /**< Number of available 
                                                             cells in direction 
                                                             'dir2' Eg. right */
                               unsigned int start_dir , /**< Start Dir-ection 
                                                             Eg. Dir = row */
                               unsigned int deny_area , /**< Deny area starting 
                                                             from start point*/
                               double *probability,     /**< Calculating
                                                             probabilty */
                               const double LOW         /**< value of LOW 
                                                             probability */
                                     );                         


/** Set the next route step in a schema with dimention (numRow,numCol), 
    using a predeterminated value of probability. The opposite probability 
    value (Eg. left right) is (1-probability).
*/
void get_direction_from_point( unsigned int numRow,/**< Number of row */
                               unsigned int numCol,/**< Number of column */
                               unsigned int *currentRow,/**< Current updated 
                                                             row.*/
                               unsigned int *currentCol,/**< Current updated 
                                                             column.*/
                               double probabilityLeft,/**< Probability to go 
                                                           left*/
                               double probabilityUp/**< Probability to go up*/
                             );


/** Increase the schema difficult, opening and closing unnecessary cells.
*/
void increase_schema_difficult( char **Map,           /**< Schema game map */
                                unsigned int numRow,  /**< Number of row */
                                unsigned int numCol   /**< Number of column */
                              );
                              

/** Save the schema game map into a new file.
*/
void save_schema_to_file( char **gameMap,/**< Schema game map*/
                          unsigned int numRow,/**< Number of row */
                          unsigned int numCol,/**< Number of column */
                          FILE *newSchemaFile/**< New schema file*/
                        );


/* End interface of schemaGameGenerator module */

#endif
