/*
 * domains.cpp
 *
 *  Created on: May 19, 2017
 *      Author: vadims
 */


//#include "readerFNN.hpp"
#include "Domains.hpp"

std::vector<Domains::domainType> Domains::existingDomainTypes;


Domains::Domains(std::string domainName, json j, std::string sKey)
{
	name = domainName;
	solverKey = sKey;
	if (j.find("sources") != j.end()) {
		for (json::iterator jt = j["sources"].begin(); jt != j["sources"].end(); ++jt) {
			InputValue val;
			val.readJson(jt.value());
			std::string propertyKey = jt.key();
			if (propertyKey.back() == '_')
				propertyKey = propertyKey.substr(0, propertyKey.size()-1);
			properties[propertyKey] = val;
		 }
	 }
	 if (j.find("id") != j.end())
		 id = j.at("id").get<int>();

	 if (j.find("matId") != j.end())
		 materialId = j.at("matId").get<int>();

	 if (j.find("enabled") != j.end())
		 enabled = j.at("enabled").get<bool>();
	 else
		 enabled = true;

	 if (j.find("isPointDomain") != j.end())
		 pointDomain = j.at("isPointDomain").get<bool>();
	 else
		 pointDomain = false;

	 if (j.find("typeKey") != j.end())
	 {
		 if (j.at("enabled").get<bool>())
		 {
			 typeKey = j.at("typeKey").get<std::string>();
		 }
		 else
		 {
			 typeKey = "none";
		 }
	 }

	 if (j.find("initialConditions") != j.end()) {
		 for (json::iterator jt = j["initialConditions"].begin(); jt != j["initialConditions"].end(); ++jt) {
			 InputValue iv;
			 iv.readJson(jt.value());
			 initialConditions[jt.key()] = iv;
		 }
	 }
	 if (j.find("groupKey") != j.end())
		 groupKey = j.at("groupKey").get<std::string>();
	 else
	 {
		 groupKey = "none";
	 }

	 if (j.find("geometryGroupKey") != j.end())
		 geometryGroupKey = j.at("geometryGroupKey").get<std::string>();
	 else
	 {
		 geometryGroupKey = "none";
	 }

	 if (j.find("domainRole") != j.end()) {
		 this->setRole(j["domainRole"]);
	 }

}


Domains::Domains(const Domains& that)
{
    	name=that.name;
    	typeKey=that.typeKey;
    	solverKey=that.solverKey;
    	id=that.id;
    	properties=that.properties;
    	initialConditions=that.initialConditions;
		materialId = that.materialId;
    	material = that.material;
    	groupKey = that.groupKey;
    	geometryGroupKey = that.geometryGroupKey;
		pointDomain = that.pointDomain;
		enabled = that.enabled;
		entities = that.entities;
		label = that.label;
}

bool Domains::operator==(const Domains& rhs) const
{
	return ( (name == rhs.name) && (typeKey == rhs.typeKey) && (solverKey == rhs.solverKey) && (id == rhs.id) && (properties == rhs.properties) );
}


std::string Domains::getPropertyValue(std::string sourceName)
{
	if (properties.find(sourceName)!= properties.end())
		return properties[sourceName].getValue();
	else
		return "0";
}

std::string Domains::getTypeKey()
{
	return Domains::typeKey;
}

std::string Domains::getGroupKey()
{
	return Domains::groupKey;
}

std::string Domains::getGeometryGroupKey()
{
	return Domains::geometryGroupKey;
}

std::string Domains::getSolverKey()
{
	if (solverKey=="none")
		return typeKey;
	else
		return Domains::solverKey;
}

int Domains::getId()
{
	return Domains::id;
}

std::string Domains::getName()
{
	return Domains::name;
}

int Domains::getMaterialId()
{
	return materialId;
}


std::map<std::string, InputValue> Domains::getInitialConditions()
{
	return Domains::initialConditions;
}

std::map<std::string, InputValue> Domains::getProperties()
{
	return Domains::properties;
}


void Domains::addProperty(std::string nm, InputValue iv)
{
	properties[nm] = iv;
}

void Domains::addInitialCondition(std::string nm, InputValue v)
{
	initialConditions[nm] = v;
}


void Domains::setGroupKey(std::string grk)
{
	groupKey = grk;
}

void Domains::setProperties(std::map<std::string, InputValue> props)
{
	properties = props;
}

bool Domains::isPointDomain()
{
	return pointDomain;
}

bool Domains::isNLDomain()
{
	for (auto& md : material.getMaterialData())
	{
		if (md.first == "BHModel")
			return true;
	}
	return false;
}

bool Domains::isEnabled()
{
	return enabled;
}

void Domains::addDomainTypes(json inp)
{
	domainType dt0(inp.at("key").get<std::string>());

	if (inp.find("properties") != inp.end()) {
		for (json::iterator kt = inp["properties"].begin(); kt != inp["properties"].end(); ++kt)
		{
			std::string propKey = kt.value().at("key");
			// omit adding variables with "_" in front
			// those values are used for ui configuration only
			if ((propKey.front() != '_') and (propKey.back() != '_'))
				dt0.properties.push_back(propKey);

			// QUICK FIX for velocity effects
			if (propKey == "_velocityEffects")
				dt0.properties.push_back(propKey);

		}
	}
	if (inp.find("material") != inp.end())
	{
		json mp_j = inp["material"];
		if (mp_j.find("properties") != mp_j.end()) {
			json mp_json = mp_j.at("properties").get<json>();
			for (json::iterator kt = mp_json.begin(); kt != mp_json.end(); ++kt) {
				json mat_data = kt.value();
				dt0.materialProps.push_back(mat_data.at("key").get<std::string>());
			}
		}
	}

	existingDomainTypes.push_back(dt0);
}

void Domains::setMaterial(Material mat)
{
	material = mat;
}

