#include"Node.h"

//Constructors for class Node
Node::Node()
{
	this->NodeName = " No Node Name is set yet";
	this->Nodetype = " No Node type is set yet";
	this->isVisited() = false;
}

//Constructors for class Node
Node::Node(string NodeType, string NodeName)
{
	this->Nodetype = NodeType;
	this->NodeName = NodeName;
	this->isVisited() = false;
}

//Desttuctor of the Node, deletes the attached Children as well
Node::~Node()
{
	for (int i = 0; i<this->CountChildren(); i++) {
		delete this->Children[i];
	}

}

//isVisited as N-Ary is traversed using a MARKING scheme, isVisited() is used to supply the bool value of visited
bool& Node::isVisited()
{
	return visited;
}


//NextUnmarkedChild finds the Next UnMarked Child
Node * Node::NextUnmarkedChild()
{
	vector<Node *>::iterator itr = Children.begin();
	int i = 0;
	while (itr != Children.end()) {
		if (!(this->Children[i]->isVisited())) {
			return this->Children[i];
		}
		itr++;
		i++;
	}
	return 0;
}

//setNodeName sets the NodeName, In Case of TextBody as nodetype, it gives text as NodeName
void Node::setNodeName(string Name)
{
	this->NodeName = Name;
}

//getNodeName returns the node name
string Node::getNodeName()
{
	return this->NodeName;
}

//setNodetype sets the Nodetype
//Note: Nodetypes passed as a string, among{Element, TextNode, PreProcessingInstruction, XMLComment
void Node::setNodetype(string Nodetype)
{
	(this->Nodetype) = Nodetype;
}

//getNodetype returns the Nodetype
//Note: Nodetypes passed as a string, among{Element, TextNode, PreProcessingInstruction, XMLComment
string Node::getNodetype()
{
	return this->Nodetype;
}

//AddChild adds a Child
void Node::AddChild(Node* Child)
{
	(this->Children).push_back(Child);
}

//CountChildren returns the number of children a Node have
int Node::CountChildren()
{
	return (this->Children).size();
}

//AddAttributes adds the attributes, to a given Node
void Node::AddAttributes(string Name, string Value)
{
	Attributes.push_back(make_pair(Name, Value));
}

//ShowAttributes displays the attributes of a Node, used by Display Node below
void Node::ShowAttributes()
{
	vector<pair<string, string>>::iterator current = this->Attributes.begin();
	while (current != this->Attributes.end())
	{
		cout << "Name: " << current->first << endl;
		cout << "Value: " << current->second << endl;
		current++;
	}
}

//AddTextBody adds a text body to the Node, in case type is NodeType
void Node::AddTextBody(string textbody)
{
	(this->NodeName) = textbody;
}

//DisplayNode displays the Node with all information
void Node::DisplayNode()
{
	if (this->getNodetype() != "Document"){
		cout << "Nodetype: " << this->getNodetype() << endl;
		cout << "NodeName: " << this->getNodeName() << endl;
		cout << "Number of Children: " << this->Children.size() << endl;
		cout << "Its Attributes " << endl;
		this->ShowAttributes();
		if (this->Nodetype == "TextBody") {
			cout << "TextBody: " << this->NodeName << endl;

		}
		cout << endl;
	}
}

//GetChild returns a Node Pointer to the ith child
Node * Node::GetChild(int i)
{
	if (i<this->CountChildren())
		return this->Children[i];
	else
		return 0;
}

//RemoveChild erases the child from the Children vector at specified position
bool Node::RemoveChild(int indexChild)
{
	vector<Node *>::iterator itr = this->Children.begin();
	itr += indexChild;
	if (indexChild<this->CountChildren()) {
		this->Children.erase(itr);
		return true;
	}
	return false;

}
//CountAttributes returns the count of attributes
int Node::CountAttributes()
{
	return this->Attributes.size();
}

//getChildByTagName returns the first child element with the tag name
Node* Node::getChildByTagName(string tagName)
{
	for (Node* child : Children) {
		if (child->NodeName == tagName)	{
			return child;
		}
	}
	return nullptr;
}
//GetAttributes returns an attribute pair with specified index
pair<string, string>Node::GetAttributes(int index)
{
	vector<pair<string, string>>::iterator current = this->Attributes.begin();
	if (index<this->CountAttributes()) {
		Attributes[index].second = Attributes[index].second.substr(1, Attributes[index].second.size() - 2);
		return Attributes[index];
	}

	pair<string, string> end;
	end.first = "end";
	end.second = "end";
	return end;
}