/*
 * bcs.h
 *
 *  Created on: May 9, 2017
 *      Author: vadims
 */

#pragma once

#include <iostream>
#include <string>
#include <map>
#include "InputValue.hpp"
#include "Material.hpp"
#include "topology/boundaryGroup.h"

typedef nlohmann::json json;

class Bcs : public BoundaryGroup
{
private:
	// properties in bc.
	// example: CHT condition q = h (T - Tref)
	// h and Tref are properties. Values can be scalar, table and expression
	struct bc_properties
	{
		std::string key;
		InputValue value;
		bc_properties(std::string key_, InputValue value_) : key(key_), value(value_) {};
	};

	struct boundaryType  // struct for available boundary types
	{
		std::string key;
		bool needs_cohomology;
		std::string boundaryGroup;
		std::vector<std::string> properties;
		std::vector<std::string> materialProps;
		boundaryType(std::string key_) : key(key_) { needs_cohomology = false; };
	};

public:

	int typeId;				// type of bc
	int domainId;			// domain id this boundary belongs to
	std::string typeKey;	// type key, corresponds to key of boundaryType
	std::string solverKey;	// solver key, important for multiphysics
	std::vector<bc_properties> properties;

	int material_id;
	Material material;
	bool has_material;
	// existing boundary types - those which are in principle possible for current physics (for current solverKey)


	Bcs();
	Bcs(std::string, json, std::string);
    ~Bcs() { };

	Bcs(const Bcs&);
    bool operator==(const Bcs& rhs) const;

	static std::vector<boundaryType> existingBoundaryTypes;

	int getId();
	int getTypeId();
	void setTypeKey(std::string);
	int getDomainId();
	int getMaterialId();
	std::string getName();
	std::string getTypeKey();
	std::string getSolverKey();
	bool hasMaterial();

    std::string getBcPropertyValue(std::string);	// returns value as string ( value or comma separated table)
    int getBcValueType(std::string); // returns Bc value type - scalar, table, expression...
    void addBcProperty(std::string, InputValue);

	std::vector<bc_properties> getProperties();

	// static method for adding existing boundary types
	static void addBoundaryTypes(json inp);

	static bool boundaryTypeExists(std::string);
	static bool boundaryTypeNeedsCohomology(std::string);
};

typedef std::shared_ptr<Bcs> Bcs_;
