/*
 * vtkForCenos.hpp
 *
 *  Created on: Oct 11, 2017
 *      Author: vadims
 */


#ifndef VTKFORCENOS_HPP_
#define VTKFORCENOS_HPP_

#include <vtkSmartPointer.h>
#include <vtkUnstructuredGrid.h>
#include <vtkMultiBlockDataSet.h>
#include <vtkMultiPieceDataSet.h>
#include <vtkEnSightWriter.h>
#include <vtkEnSightGoldBinaryReader.h>
#include <map>
#include <complex>

class cenosEnsightWriter;
class vtkForCenos {
	vtkSmartPointer<vtkMultiPieceDataSet> multiPieceDataSet;
	vtkSmartPointer<vtkMultiBlockDataSet> multiBlockDataSet;
	vtkSmartPointer<vtkUnstructuredGrid> unstructuredGrid;
	vtkSmartPointer<cenosEnsightWriter> _ens_writer;
	vtkSmartPointer<vtkEnSightGoldBinaryReader> _ens_reader;
	std::vector<vtkSmartPointer<vtkUnstructuredGrid> > ugridVec;
	std::vector<std::string> writtenFields_Blocks;
	std::map< int, int > indMap;
	std::vector<std::string> ugridBlockNames;
	std::vector<std::pair<std::string, int>> dataSets;
	void fillEmptySets(int);


	std::vector<double> tsteps;
	int nrOfSteps;

public:
	vtkForCenos();
	void enterDataSet(std::string, int );

	// merges severaal legacy vtk files into one, return file name
	std::string mergeVTK(std::vector<std::string>, std::vector<int>, std::string, std::string, std::vector<float>&);
	
	// sets transient geometry (for transient cases)
	void setTransientGeometry(bool);

	// sets output path to path and filename to basename for output
	int setOutput(std::string path, std::string basename);

	//get last time step in previously written results
	float getLastTimeInSet();

	void setContinuation(double zerothTimeValue = 0);

	//Adds block to multiBlockDataSet
	// nodeVec is vector of node id and coordinates - nodeId, node.x(), node.y(), node.z()
	// elementVec is vector of element type and nodes - elementVtkType, node1_id, node2_id...
	// entityId is id of line, surface or volume entity
	int addBlockToGrid(std::vector<std::vector<float> > nodeVec, std::vector<std::vector<int> > elementVec, int entityId, float meshScale);

	int addUGrid(vtkSmartPointer<vtkUnstructuredGrid>, int);

	vtkSmartPointer<vtkUnstructuredGrid> getGrid(int);
	// Reads data from resFile and adds point field with name fieldname to block with blockId

	int addCurrentPointFieldToBlock(std::ifstream &, std::string, int);
	int addCurrentPointVectorFieldToBlock(std::ifstream &, std::string, int);
	int addCurrentCellFieldToBlock(std::ifstream &, std::string, int);
	int addZeroPointFieldToBlock(std::string, int);
	int addZeroPointFieldToBlock_(std::string, int);
	int addZeroPointVectorFieldToBlock(std::string, int);
	int addZeroPointVectorFieldToBlock_(std::string, int);
	int addZeroCellFieldToBlock(std::string, int);

	bool fieldIsAdded( std::string, int );


	//writes output for specified timestep. Current data has to be set before executing this method
	int writeTimeStep(double time);

	//sets block names
	int setBlockNames(std::vector<int> ids, std::vector<std::string> blockNames);

	// cleans blocks before timestep
	int newTimeStep();

	// writes case file which contains references to all time data
	int finalize();

	void writePolyDataToVTK(int entNr, std::string outFileName);

	std::vector<float> getPolyPoints(int entNr);
	std::vector<int> getPolyElements(int entNr);
	std::vector<int> getElementSizeArray(int);
	void writeVTKlog(const std::string &);

	void writeLegacyVTK(float, std::vector<std::string>);

	void addTimeStepValue(double time);
};



class cenosEnsightWriter: public vtkEnSightWriter {
	std::map<int, std::string> nameList;
   public:
	void WriteOCaseFile(int , std::vector<double> );
	void WriteData();
	void WriteStringToFile(const char* cstring, FILE* file);
	void WriteTerminatedStringToFile(const char* cstring, FILE* file);

	void WriteIntToFile(const int i, FILE* file);
	void WriteFloatToFile(const float f, FILE* file);
	FILE* OpenFile(char* name);
	void setNameList(std::vector<int>, std::vector<std::string>);

	static cenosEnsightWriter *New();
};




#endif /* VTKFORCENOS_HPP_ */
