/*
 * bcs.cpp
 *
 *  Created on: May 9, 2017
 *      Author: vadims
 */

#include "Bcs.hpp"


std::vector<Bcs::boundaryType> Bcs::existingBoundaryTypes;

Bcs::Bcs()
{
}

Bcs::Bcs(std::string bcName, json j, std::string sKey)
{
	 name = bcName;
	 solverKey = sKey;
	 if (j.find("values") != j.end()) {
	 	 for (json::iterator jt = j["values"].begin(); jt != j["values"].end(); jt++) {
	 		 InputValue value;
			 value.readJson(jt.value());
	 		 std::string valueKey = jt.key();
	 		 if (valueKey.back() == '_')
	 			valueKey = valueKey.substr(0, valueKey.size()-1);
			 properties.push_back(bc_properties(valueKey, value));
	 	 }
	 }
	 if (j.find("id") != j.end())
		 id = j.at("id").get<int>();
	 else
		 id = 0;
	 if (j.find("domainId") != j.end())
		 domainId = j.at("domainId").get<int>();
	 if (j.find("typeId") != j.end())
		 typeId = j.at("typeId").get<int>();

	 has_material = false;
	 if (j.find("matId") != j.end())
		 if (!j.at("matId").is_null())
		 {
			 material_id = j.at("matId").get<int>();
			 has_material = true;
		 }

	 if (j.find("typeKey") != j.end())
		 typeKey = j.at("typeKey").get<std::string>();
	 else
		 typeKey = "none";
}

Bcs::Bcs(const Bcs& that)
{
	name=that.name;
	typeKey=that.typeKey;
	typeId=that.typeId;
	domainId=that.domainId;
	id=that.id;
	properties = that.properties;
	solverKey = that.solverKey;
	material_id = that.material_id;
	has_material = that.has_material;
	entities = that.entities;
	label = that.label;
}

bool Bcs::operator==(const Bcs& rhs) const
{
	return ( (name == rhs.name));
	//return ( (name == rhs.name) && (typeKey == rhs.typeKey) && (domainId == rhs.domainId) && (id == rhs.id) && (solverKey == rhs.solverKey) );
}



std::string Bcs::getSolverKey()
{
	if (typeKey=="none")
		return typeKey;
	else
		return Bcs::solverKey;
}

bool Bcs::hasMaterial()
{
	return has_material;
}


int Bcs::getDomainId()
{
	return Bcs::domainId;

}

int Bcs::getMaterialId()
{
	return material_id;
}


int Bcs::getTypeId()
{
	return Bcs::typeId;
}



std::string Bcs::getTypeKey()
{
	return Bcs::typeKey;
}

void Bcs::setTypeKey(std::string str)
{
	Bcs::typeKey = str;
}

int Bcs::getId()
{
	return Bcs::id;
}

std::string Bcs::getName()
{
	return Bcs::name;
}

std::vector<Bcs::bc_properties> Bcs::getProperties()
{
	return properties;
}



std::string Bcs::getBcPropertyValue(std::string valueName)
{
	for (auto pp : properties)
	{
		if (pp.key == valueName)
			return pp.value.getValue();
	}
	return "0";
}

int Bcs::getBcValueType(std::string valueName)
{
	for (auto pp : properties)
	{
		if (pp.key == valueName)
			return pp.value.getTypeId();
	}
	return 0;
}



void Bcs::addBcProperty(std::string nm, InputValue iv)
{
	bc_properties bp(nm, iv);
	properties.push_back(bp);
}

bool Bcs::boundaryTypeExists(std::string key_)
{
	for (auto& bt : existingBoundaryTypes)
	{
		if (bt.key == key_)
			return true;
	}
	return false;
}

bool Bcs::boundaryTypeNeedsCohomology(std::string key_)
{
	for (auto& bt : existingBoundaryTypes)
	{
		if (bt.key == key_)
		{
			if (bt.needs_cohomology)
				return true;
			else
				return false;
		}
	}
	return false;
}


void Bcs::addBoundaryTypes(json inp)
{
	for (json::iterator jt = inp.begin(); jt != inp.end(); jt++)
	{
		json bt_data = jt.value();
		std::string key_;

		if (bt_data.find("key") != bt_data.end()) {
			key_ = bt_data.at("key").get<std::string>();
		}

		// create instance of boundaryType if it does not exist
		if (!boundaryTypeExists(key_))
		{
			boundaryType bt0(key_);

			if (bt_data.find("properties") != bt_data.end()) {
				for (json::iterator kt = bt_data["properties"].begin(); kt != bt_data["properties"].end(); kt++)
				{
					std::string propKey = kt.value().at("key");
					bt0.properties.push_back(propKey);
				}
			}
			if (bt_data.find("material") != bt_data.end())
			{
				json mp_j = bt_data["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();
						bt0.materialProps.push_back(mat_data.at("key").get<std::string>());
					}
				}
			}
			existingBoundaryTypes.push_back(bt0);
		}
	}
}


