/*
 * PostValues.hpp
 *
 *  Created on: Sep 13, 2017
 *      Author: vadims
 */

#ifndef POSTVALUES_HPP_
#define POSTVALUES_HPP_

#include <iostream>
#include <optional>
#include "nlohmann/json.hpp"
#include "Domains.hpp"


using json = nlohmann::json;

class PostValues
{


public:

	bool isEnabled();

	void setEnabled(bool);
	// get Id (number) of postValue
	int getId();

	// get Id (string) of postValue
	std::string getStringId();

	// get name of postValue
	std::string getName();

	// get label of postValue
	std::string getLabel();

	// get symbol of postValue
	std::string getSymbol();

	// get the units of postValue
	std::string getUnits();

	// get name of postValue without commas (replaced by space)
	std::string getNameNoCommas();

	// get register number which uses GetDP
	int getValueRegister();

	std::string getEquationForScaling();
	std::string getEnablingField();


	//get E field (for NTFF)
	std::string getEfield();	
	
	//get H field (for NTFF)
	std::string getHfield();

	//does it require storing in variable?
	bool storeInVariable();

	// true if value is intermediate
	bool isIntermediate();
       //true if need a loop in PostOp for multiport 
	bool needLoop();

	//true if has two different possibilities of term
	bool hasTwoTerm();

	std::vector<std::string> getScalingConstraints();
	// if true, outputs sum of postValue values across all domains
	bool getSumAllDomains();



	struct args {
		int id;
		std::string phys;
		std::string replaceStr;
		args(int id_, std::string phys_, std::string replaceStr_) :
			id(id_), phys(phys_), replaceStr(replaceStr_) {};
		int getId()
		{
			return id;
		}
		std::string getPhys()
		{
			return phys;
		}
		std::string getReplaceString()
		{
			return replaceStr;
		}
	};


	// get type of postValue
	// type of postValues:
	// 0 for nodal
	// 1 for elemental
	// 7 for global values in bcs
	// 8 for global variables in domains
	// 9 for integral

	enum PostValueType
	{
		NODE_FIELD,
		BOUNDARY_NODE_FIELD,  //was 2
		INTEGRAL, //was 9
		BOUNDARY_INTEGRAL, //was 10
		GLOBAL, //was 8
		BOUNDARY_GLOBAL, //was 7
		RESIDUAL, // was 77
		MAX_VAL, //was 78
		RESIDUAL_FOR_ADAPTIVE, //was 80
		TOTAL_VALUE,
		BOUNDARY_CELL_FIELD,
		FAR_FIELD,
		INTERMEDIATE_VOL,
		INTERMEDIATE_SUR,
		CIRCULATION,
		GLOBAL_EXTERNAL,
		SCALING_VALUE
	};

	static std::optional<PostValueType> getPostType(std::string pt);


	PostValueType getType();

	std::vector<args> argList;
	std::vector<std::string> getTerms();
	std::vector<std::string> getTerms2();
	std::vector<std::string> getDomains();
	std::vector<std::string> getSubDomains();

	int getSmoothing();
	int getNumComponents();
	std::string getSolverKey();
	void setPhysicsKey(std::string);
	void setSolverKey(std::string);
	bool needsExportToVTK();
	void setExportToVTK(bool);
	void setEHfields(std::string, std::string);
	void setStoreInVariable(bool);
	void setIntermediate(bool);
	void setNeedLoop(bool);
	void setHasTwoTerm(bool);

	// checks if postValue is defined in domains with group name
	// argument - vector of group names
	// returns true if postValue is defined for at least one group
	bool isDefinedInDomain(std::string);

	//for multiport
	bool isDefinedInDomainMultiPort(std::string);



	void addArguments(int, std::string, std::string);

	PostValues(std::string, json);

	PostValues& operator=(const PostValues&);
	PostValues(const PostValues& p2);

	bool isExternal();
	json getExternalData();

private:
	std::string name;
	std::string label;
	std::string symbol;
	std::string units;
	std::vector<std::string> term;
	std::vector<std::string> term2;
	std::vector<std::string> definedDomains, definedSubDomains;
	std::string string_id;
	std::string solver_key;
	std::string physics_key;
	json external_data;
	int id;
	int smooth;
	int ncomp;
	int valueRegister;
	std::string equation_for_scaling;
	std::string enable_if_defined;
	bool exportToVTK;
	bool enabled;
	bool storeInVariable_;
	bool isIntermediate_;
        bool needLoop_;
	bool hasTwoTerm_;

	std::vector<std::string> scaling_constraints;

	//for far field calculation
	std::string Efield;
	std::string Hfield;

	PostValueType type;
	bool external;
	bool sumAllDomains;

};


#endif /* POSTVALUES_HPP_ */
