
#pragma once

#ifndef Matrix2d_h
#define Matrix2d_H

#include "b_file.h"
#include "garray.h"
//matiz de clases genericas de 2 dimensiones
template <typename Tc>
class ComClasFunction
{
public:
	virtual Tc comp(Tc a, Tc b) = 0;
};
template <typename ClasVal>
class Matrix2d
{
	Cgarray<ClasVal> dat;
	int ysize;
public:
	Matrix2d()
	{
		ysize = 0;
	}
	bool inline inicia(int xmax, int ymax)
	{
		ysize = ymax;
		dat.borra();
		if(!(dat+=xmax*ymax))
			return false;
		dat.n = xmax*ymax;
		return true;
	}
	
	inline  ClasVal* operator[](int x)//devuelve puntero a fila x
	{
		return dat.get(x*ysize);
	}
	
	//*******************************************************************************************************

	inline bool graba( char* path )
	{
		Cb_file file;
		if(!file.abre(path,2,TRUE))
			return false;
		if(!file.escribe(&ysize, sizeof(ysize)))
			return false;
		if(!dat.graba(&file))
			return false;
		return true;
	}
	inline bool lee( char* path )
	{
		Cb_file file;
		if(!file.abre(path,1,FALSE,TRUE))
			return false;
		if(!file.lee(&ysize, sizeof(ysize)))
			return false;
		if(!dat.leer(&file))
			return false;
		return true;
	}
	inline void clear()
	{
		dat.borra();
	}
	inline bool fileMix( char* path, ComClasFunction<ClasVal> *ccomp )
	{
		if(ysize<=0)
			return false;
		Cgarray<ClasVal> fdat;
		int yfile, xfile;
		Cb_file file;
		if(!file.abre(path,1,FALSE,TRUE))
			return false;
		//lee tamaņo matriz
		if(!file.lee(&yfile, sizeof(yfile)))
			return false;
		if(!file.lee(&xfile, sizeof(xfile)))
			return false;
		xfile = xfile/yfile;
		//inicia buffer
		if(!(fdat+=yfile))
			return false;
		//calcula numero de bytes a leer y margenes de matriz
		int nb = sizeof(ClasVal)*yfile;
		xfile = min(xfile, dat.n/ysize);
		yfile = min(yfile, ysize);
		for(int x = 0 ; x<xfile; x++)
		{
			//lee fila
			if(!file.lee(fdat.ptr, nb))
				return false;
			//realiza el mix
			for(int y = 0; y< yfile; y++)
				dat.get(x*ysize)[y] = ccomp->comp(dat.get(x*ysize)[y], fdat[y]);				
		}
	
		return true;
	}
};
#endif