#include "Element.hpp"

/*
 * element.cpp
 *
 *  Created on: May 9, 2017
 *      Author: vadims
 */
#include <vector>
#include <cmath>
#include <algorithm>
#include <iostream>
#include "MeshEntity.h"
#include "ElementTypes.hpp"



Element::Element()
{
	mark = 0;
}

Element::~Element()
{
	mark = 0;
}

/**
 * Element copy constructor
*/
Element::Element(const Element& that) {
	nodes = that.nodes;
	id = that.id;
	ownerEntity = that.ownerEntity;
	mark = that.mark;
}

Element::Element(std::shared_ptr<MeshEntity> owner, std::vector<std::shared_ptr<Node>> nodelist)
{
	this->ownerEntity = owner;
	this->nodes.assign(nodelist.begin(), nodelist.end());
	mark = 0;
}

std::shared_ptr<Element> Element::createElement(ElementTypes elementType)
{
	if (elementType == LINE)
		return std::make_shared<LINEelement>();
	else if (elementType == TRI)
		return std::make_shared<TRIelement>();
	else if (elementType == QUAD)
		return std::make_shared<QUADelement>();
	else if (elementType == TETRA)
		return std::make_shared<TETRAelement>();
	else if (elementType == HEXA)
		return std::make_shared<HEXAelement>();
	else if (elementType == PRISM)
		return std::make_shared<PRISMelement>();
	else if (elementType == PYRA)
		return std::make_shared<PYRAelement>();
	else if (elementType == LINE_2)
		return std::make_shared<LINE2element>();
	else if (elementType == TRI_2)
		return std::make_shared<TRI2element>();
	else if (elementType == TETRA_2)
		return std::make_shared<TETRA2element>();
	else
		return std::make_shared<LINEelement>();
}

bool Element::operator==(const Element& rhs) const
{
	return this->id == rhs.id;
}

bool Element::operator!=(const Element& rhs) const
{
	return this->id!= rhs.id;
}

int Element::getId()
{
	return id;
}


std::vector<std::shared_ptr<Node>> Element::getNodes()
{
	return std::vector<std::shared_ptr<Node>>(nodes.begin(), nodes.end());
}

int Element::getElementType()
{
	return elType;
}

int Element::getElementVTKType()
{
	return vtkType;
}

std::string Element::getElementStringType()
{
	return stringType;
}


std::shared_ptr<MeshEntity> Element::getOwnerEntity()
{
	return ownerEntity.lock();
}

bool Element::hasAllNodesOf(std::shared_ptr<Element> el)
{
	for (auto nd : el->getNodes())
	{
		bool found = false;
		for (auto lnd : nodes)
		{
			if (lnd.lock() == nd) {
				found = true;
				break;
			}
		}
		if (!found)
			return false;
	}
	return true;
}




Element::Dim Element::getDimension()
{
	return dimension;
}

int Element::getTypeNodeCount()
{
	return typeNodeCount;
}

int Element::getMark()
{
	return mark;
}


void Element::setNodes(std::vector<std::shared_ptr<Node>> nds)
{
	this->nodes.assign(nds.begin(), nds.end());
}

void Element::setId(int id )
{
	this->id = id;
}

void Element::setEntity(std::shared_ptr<MeshEntity> entity)
{
	this->ownerEntity = entity;
}

void Element::setMark(int m)
{
	mark = m;
}

std::vector<double> Element::getCentroid()
{
	double cx = 0, cy = 0, cz = 0;
	for (auto n : nodes)
	{
		cx = cx + n.lock()->x();
		cy = cy + n.lock()->y();
		cz = cz + n.lock()->z();
	}
	cx = cx / nodes.size();
	cy = cy / nodes.size();
	cz = cz / nodes.size();
	return { cx, cy, cz };
}

