/*
 * Physics.h
 *
 *  Created on: May 8, 2017
 *      Author: vadims
 */

#ifndef PHYSICS_H
#define PHYSICS_H

#include <string>
#include <iostream>
#include <map>
#include <vector>
#include "Material.hpp"
#include "Bcs.hpp"
#include "Domains.hpp"
#include "InputValue.hpp"
#include "PostValues.hpp"
#include "Flag.hpp"
#include "nlohmann/json.hpp"

using json = nlohmann::json;

class Physics
{
public:
	enum timeType {
		STEADY = 1,
		TRANSIENT = 2,
		HARMONIC_WITH_TIME = 3, // e.g. for Induction heating, where harmonic solver is used in time
		MULTIHARMONIC = 6,
		HARMONIC = 7 
	};

	enum symmetryType {
		PLANAR_2D = 1,
		AXISYMMETRIC_2D = 2,
		FULL_3D = 3,
		SECTOR_3D = 4
	};
	bool multiInput;


private:
	// keys
	std::string physicsKey;
	std::string subPhysicsKey;
	std::string basisKey;
	std::string solverKey;
	std::string multiSubPhysicsKey;

	//data: materials, bcs, domains
	std::vector<Material> matList;
	std::vector<Bcs_> boundariesList;
	std::vector<Domains_> domainsList;
	std::vector<Flag> flags;

	// time type

	timeType timeTypeId;


	//symmetry type

	symmetryType symmetryTypeId;
	// depthZ - for 2D_PLANAR
	// symmFactor = for 3D_SECTOR
	float depthZ, symmFactor;

	static std::map<std::string, InputValue> constants;

	//map with time parameters (start time, end time, time step, etc.)
	std::map<std::string, InputValue> timeParameters;

	//map with solver parameters (tolerance, relaxation factor, etc.)
	std::map<std::string, InputValue> solverParameters;

	std::vector<std::shared_ptr<PostValues>>  postValueList;

public:

    Physics() {};
	Physics(json input) { readInput(input); };
    ~Physics() { };

	void readPhysicsConfig(json inp);
	static void readConstants(json physicsConfigJson);
	void readPostValues(json, json);
	void readInput(json inp);

	std::string getSolverKey();
	std::string getPhysicsKey();
	std::string getSubPhysicsKey();
	std::string getMultiSubPhysicsKey();
	std::string getBasisKey();
	std::string getLastPort();
	bool getMultiInput();


	std::vector<std::shared_ptr<PostValues>>  getPostValues();
	std::vector<std::shared_ptr<PostValues>>  getEnabledPostValueList();
	std::vector<std::string> getGroupNamesOfDomainType(std::string domTypeName);
	std::vector<std::string> getGroupNamesOfBoundaryType(std::string bcTypeName);

	float getGeometricFactor();
	float getSymmFactor();

	symmetryType getSymmetryType();
	timeType getTimeType();
	Material getMaterialById(unsigned int);
	std::vector<Bcs_> getBoundariesList();
	std::vector<Domains_> getDomainsList();
	std::vector<Material> getMaterialsList();

	Bcs_ getBoundaryByName(std::string n);

	static std::map<std::string, InputValue> getConstants();
	std::vector<Flag> getFlags();
	std::map<std::string, InputValue> getTimeParameters();
	std::map<std::string, InputValue> getSolverParameters();

	void setTimeParameter(std::string, float);

	bool hasNonlinearProps();

	void addDomain(Domains_ dom);
	void addBoundary(Bcs_ bnd);
	void addFlag(Flag fl);
	void setFlagValue(std::string, bool);

	void changeInitializationForRestart();

	void validateInput();

};

#endif




