/*!\file:  OutputResultsx.cpp
 * \brief: go through our finite elements, and see what results they have stored within. 
 * Then output them into serialized patch arrays, and dump to disk.
 */ 

#ifdef HAVE_CONFIG_H
	#include <config.h>
#else
#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
#endif

#include <stdio.h>
#include "./OutputResultsx.h"
#include "../../Container/Container.h"
#include "../../io/io.h"
#include "../../classes/objects/objects.h"

void OutputResultsx(Elements* elements, Nodes* nodes, Vertices* vertices, Loads* loads, Materials* materials, Parameters* parameters,Results* results){

	int         my_rank;
	FILE       *fid                     = NULL;
	char       *outputfilename          = NULL;
	char        cpu_outputfilename[100];        //easier to convert an integer with sprintf
	bool        io_gather;
	int         solutiontype;
	char*       solutiontypestring      = NULL;
	bool        dakota_analysis         = false;

	/*retrieve parameters: */
	parameters->FindParam(&dakota_analysis,QmuIsdakotaEnum);

	/*recover my_rank:*/
	my_rank=IssmComm::GetRank();

	if(dakota_analysis){
		//no need to output anything, Dakota analysis has different outputs
		return; 
	}

	/*We have results inside our elements, loads, etc ... Get them out of there, into the results dataset: */
	elements->ProcessResultsUnits();
	elements->ToResults(results,parameters);
	elements->DeleteResults();

	/*Results do not include the type of solution being run	. In parallel, we output results to a filename, 
	 *therefore, we need to include the solutiontype into the filename: */
	if(my_rank==0){
		parameters->FindParam(&solutiontype,SolutionTypeEnum);
		EnumToStringx(&solutiontypestring,solutiontype);
		results->AddObject(new GenericExternalResult<char*>(results->Size()+1,SolutionTypeEnum,solutiontypestring,1,0));
		xDelete<char>(solutiontypestring);
	}

	/*Now, open file for writing, if not already done: */
	if(!parameters->Exist(OutputFilePointerEnum)){

		/*We don't have a file pointer. Retrieve the output file name and open it for writing:*/
		parameters->FindParam(&outputfilename,OutputFileNameEnum);

		/*What strategy? : */
		parameters->FindParam(&io_gather,SettingsIoGatherEnum);

		if(io_gather){
			/*Just open the file for output on cpu 0. We are gathering the data on cpu 0 from all other cpus: */
			if(my_rank==0) fid=pfopen(outputfilename ,"wb");
		}
		else{
			/*We are opening different  files for output on all cpus. Append the  rank to the filename, and open: */
			parameters->FindParam(&fid,OutputFilePointerEnum);
			sprintf(cpu_outputfilename,"%s.%i",outputfilename,my_rank);
			fid=pfopen(cpu_outputfilename ,"wb");
		}
		xDelete<char>(outputfilename);

		/*Add file pointer in parameters for further calls to OutputResultsx: */
		parameters->SetParam(fid,OutputFilePointerEnum);
	}

	/*Write results to disk: */
	results->Write(parameters);

	/*Delete and reinitialize results, in parallel: */
	results->clear();

	/*Close output file? :*/
	/*WARNING: issm.cpp is taking care of it for now (quick fix)
	  if((step==1) && (time==0)){
	  if(io_gather){
	  if(my_rank==0) pfclose(fid,outputfilename);
	  }
	  else pfclose(fid,cpu_outputfilename);
	  }
	*/
}
