/* \file IoModel.h
 * \brief  Header file defining the IoModel structure that will help in processing the input data coming 
 * into ISSM, from Matlab, or through a binary file opened for reading.
 * \sa IoModel.cpp
 */

#ifndef _IOMODEL_H
#define _IOMODEL_H

#include "../shared/Enum/Enum.h"

class Parameters;
class Elements;
class Param;
class Option;

class IoModel {

	private: 
		Parameters *constants;   //this dataset holds all IssmDouble, int, bool and char from input

	public:
		IssmDouble **data;   //this dataset holds temporary data, memory intensive.

		/*pointer to input file*/
		FILE *fid;

		/*Partitioning*/
		bool *my_elements;
		int  *my_vertices;

		/*Mesh properties and connectivity tables*/
		int  meshtype;
		int  numberofvertices;
		int  numberofelements;
		int  numberoffaces;
		int  numberofedges;
		int *elements;
		int *faces;
		int *edges;
		int *elementtoedgeconnectivity;
		int *elementtofaceconnectivity;
		int *singlenodetoelementconnectivity;
		int *numbernodetoelementconnectivity;

		/*Data to synchronize through low level object drivers: */
		int nodecounter;         //keep track of how many nodes are being created in each analysis
		int loadcounter;         //keep track of how many loads are being created in each analysis
		int constraintcounter;   //keep track of how many constraints are being created in each analysis

		/*for AD mode: to keep track of our independent variables we fetch:*/
		bool    *independents;
		DataSet *independent_objects;

		/*Methods*/
		~IoModel();
		IoModel();
		IoModel(FILE* iomodel_handle);

		/*Input/Output*/
		void        CheckEnumSync(void);
		void        Constant(bool *poutput,int constant_enum);
		void        Constant(int *poutput,int constant_enum);
		void        Constant(IssmDouble *poutput,int constant_enum);
		void        Constant(char **poutput,int constant_enum);
		Param      *CopyConstantObject(int constant_enum);
		IssmDouble *Data(int dataenum);
		void        DeleteData(int num,...);
		void        DeleteData(IssmDouble* vector, int dataenum);
		void        DeleteData(char*** pstringarray, int numstrings, int dataenum);
		void        FetchConstants(void);
		void        FetchData(bool* pboolean,int data_enum);
		void        FetchData(int* pinteger,int data_enum);
		void        FetchData(IssmDouble* pscalar,int data_enum);
		void        FetchData(char** pstring,int data_enum);
		void        FetchData(int** pmatrix,int* pM,int* pN,int data_enum);
		void        FetchData(IssmDouble**  pscalarmatrix,int* pM,int* pN,int data_enum);
		void        FetchData(char***   pstringarray,int* pnumstrings,int data_enum);
		void        FetchData(IssmDouble*** pmatrixarray,int** pmdims,int** pndims, int* pnumrecords,int data_enum);
		void        FetchMultipleData(char***   pstringarray,int* pnumstrings,int data_enum);
		void        FetchMultipleData(IssmDouble*** pmatrixarray,int** pmdims,int** pndims, int* pnumrecords,int data_enum);
		void        FetchMultipleData(int*** pmatrices,int** pmdims,int** pndims, int* pnumrecords,int data_enum);
		void        FetchMultipleData(int** pvector, int* pnum_instances,int data_enum);
		void        FetchData(Option **poption,int data_enum);
		void        FetchData(int num,...);
		void        FetchDataToInput(Elements* elements,int vector_enum);
		void        FetchDataToInput(Elements* elements,int vector_enum,IssmDouble default_value);
		void        LastIndex(int *pindex);
		FILE*       SetFilePointerToData(int* pcode,int* pvector_type, int data_enum);
		fpos_t*     SetFilePointersToData(int** pcodes,int** pvector_types, int* pnum_instances, int data_enum);
		void        DeclareIndependents(void);
		void        StartTrace(void);
		void        FetchIndependent(int dependent_enum);
};

#endif  /* _IOMODEL_H */
