#include <i3d/image3d.h>
#include <i3d/transform.h>
#include <i3d/morphology.h>

#include <stdlib.h> //for rnd generator seeding
#include <time.h>
#include <unistd.h>
#include <string.h>

#include "params.h"
#include "graphics.h"
#include "TriangleMesh.h"

//create some shared objects...
ParamsClass params;
void ParamsSetup(void);
//
ActiveMesh mesh;

bool LoadNewMesh(const char* path,const int ID,const int fileNo,const bool keepTrajectories=false);

int main(int argc,char **argv)
{
	if (argc == 1)
	{
		//I'm executed with no params, provide help
		std::cout << "ADD SOME HEADER INFORMATION HERE\n\n";
		std::cout << "params:  cell_surf_mesh  filo1_description [filoN_description]  out_mesh.stl\n\n";
		std::cout << "The program will try to load object files (cell body surface mesh -- the\n"
                   "first parameter) and (filopodia skeleton definitions -- the second till the last\n"
                   "but one parameter(s)) and save them in one mesh (the last parameter).\n";
		return(-1);
	}

	//init the situation...
	ParamsSetup();

	//read cell body
	std::cout << "reading cell body: " << argv[1] << "\n";
	int retval=mesh.ImportVTK(argv[1]);
	if (retval) 
	{
		std::cout << "some error reading cell body: " << retval << "\n";
		return(1);
	}

	//read filopodia files
	for (int i=0; i < argc-3; ++i)
	{
		std::cout << "reading filopodium: " << argv[2+i] << "\n";
		retval=mesh.ImportVTK_Ftree(argv[2+i],999999);
		if (retval) 
		{
			std::cout << "some error reading filopodium: " << retval << "\n";
			return(2);
		}
	}

	std::cout << "vertices   #: " << mesh.Pos.size() << "\n";
	std::cout << "triangles  #: " << mesh.ID.size()/3 << "\n";
	std::cout << "normals    #: " << mesh.norm.size() << "\n";

	std::cout << "filopodia #: " << mesh.Ftree.size() << "\n";
	for (size_t f=0; f < mesh.Ftree.size(); ++f)
	{
		std::cout << f << ": vertices  #: " << mesh.Ftree[f].Pos.size() << "\n";
		std::cout << f << ": triangles #: " << mesh.Ftree[f].ID.size()/3 << "\n";
		std::cout << f << ": normals   #: " << mesh.Ftree[f].norm.size() << "\n";
	}

	//export the all meshes
	std::cout << "saving mesh: " << argv[argc-1] << "\n";
	mesh.ExportSTL(argv[argc-1]);
	return(0);
}


void ParamsSetup(void)
{
	//set up the environment
   params.sceneOffset=Vector3d<float>(0.f);
   params.sceneSize=Vector3d<float>(27.5f,27.5f,22.0f); //for sample cell

	params.sceneCentre=params.sceneSize;
	params.sceneCentre/=2.0f;
	params.sceneCentre+=params.sceneOffset;

	params.sceneOuterBorder=Vector3d<float>(2.f);
	params.sceneBorderColour.r=0.7f;
	params.sceneBorderColour.g=0.7f;
	params.sceneBorderColour.b=0.0f;

	params.inputCellsFilename="cells/cell%d.txt";
	params.numberOfAgents=2;

	params.friendshipDuration=10.f;
	params.maxCellSpeed=0.20f;

	//adapted for cell cycle length of 24 hours
	params.cellCycleLength=14.5*60; //[min]

	params.currTime=0.0f; //all three are in units of minutes
	params.incrTime=1.0f;
	params.stopTime=50.0f;

	params.imgSizeX=500; //pixels
	params.imgSizeY=500;
	params.imgResX=1.0f; //pixels per micrometer
	params.imgResY=1.0f;

	params.imgOutlineFilename="Outline%05d.tif";
	params.imgPhantomFilename="Phantom%05d.tif";
	params.imgMaskFilename="Mask%05d.tif";
	params.imgFluoFilename="FluoImg%05d.tif";
	params.imgPhCFilename="PhCImg%05d.tif";
	params.tracksFilename="tracks.txt";


	//re-seed the standard rnd generator
	//(which is used for Perlin texture)
	unsigned int seed=(1 << 20) * (unsigned int)time(NULL) * (unsigned int)getpid();
	srand(seed);
}


bool LoadNewMesh(const char* path,const int ID,const int fileNo,const bool keepTrajectories)
{
	//this function is here only because the graphics.cpp module references it
	//but graphics is not used in this module at all...

	//this is here to get rid of warnings...
	int a=(int)path[0];
	a+=fileNo;
	a+=ID;
	a+=(keepTrajectories)? 1 : 0;
	return(true);
}
