#include "Vertex.h"

Vertex::Vertex() {

}

Vertex::Vertex(const int& id, const char& type) {
	this->id = id;
	this->type = type;
	this->word = -1;
	this->bitKey = -1;
}

Vertex::Vertex(const Vertex& v) {
	this->id = v.id;
	this->type = v.type;
	this->word = v.word;
	this->bitKey = v.bitKey;
	this->inGoingArcs = v.inGoingArcs;
	this->outGoingArcs = v.outGoingArcs;
	this->extendedPredecessors = v.extendedPredecessors;
	this->ngSet = v.ngSet;
}

Vertex::~Vertex() {

}

bool operator==(const Vertex& v1, const Vertex& v2) {
	return v1.id == v2.id;
}

bool operator!=(const Vertex& v1, const Vertex& v2) {
	return !(v1 == v2);
}

Vertex& Vertex::operator=(const Vertex& v) {
	this->id = v.id;
	this->type = v.type;
	this->word = v.word;
	this->bitKey = v.bitKey;
	this->inGoingArcs = v.inGoingArcs;
	this->outGoingArcs = v.outGoingArcs;
	this->extendedPredecessors = v.extendedPredecessors;
	this->ngSet = v.ngSet;
	return *this;
}

void Vertex::addInGoingArc(const int& id, const int& weight) {
	assert(this->id != id);
	assert(this->inGoingArcs.find(id) == this->inGoingArcs.end());
	this->inGoingArcs.insert(make_pair(id, weight));
}

void Vertex::addOutGoingArc(const int& id, const int& weight) {
	assert(this->id != id);
	assert(this->outGoingArcs.find(id) == this->outGoingArcs.end());
	this->outGoingArcs.insert(make_pair(id, weight));
}

void Vertex::removeInGoingArc(const int& id) {
	this->inGoingArcs.erase(id);
}

void Vertex::removeOutGoingArc(const int& id) {
	this->outGoingArcs.erase(id);
}

void Vertex::addExtendedPredecessor(const int& id) {
	assert(id >= 0);
	this->extendedPredecessors.push_back(id);
}

void Vertex::initializeNgSet(const int& wordsNumber) {
	this->ngSet = vector<int>(wordsNumber, 0);
}


void Vertex::addNgNeighbour(const int& word, const int& bitKey) {
	assert((this->ngSet.at(word) & bitKey) == 0);
	this->ngSet.at(word) += bitKey;
}

const int& Vertex::getId() const {
	return this->id;
}
const char& Vertex::getType() const {
	return this->type;
}
const int& Vertex::getWord() const {
	return this->word;
}
const int& Vertex::getBitKey() const {
	return this->bitKey;
}
const unordered_map<int, int>& Vertex::getInGoingArcs() const {
	return this->inGoingArcs;
}
const unordered_map<int, int>& Vertex::getOutGoingArcs() const {
	return this->outGoingArcs;
}
const vector<int>& Vertex::getExtendedPredecessors() const {
	return this->extendedPredecessors;
}
const vector<int>& Vertex::getNgSet() const {
	return this->ngSet;
}

void Vertex::setWord(const int& word) {
	this->word = word;
}
void Vertex::setBitKey(const int& bit) {
	this->bitKey = bit;
}

const string Vertex::toString(const bool& printAdjacencyLists) const {
	string str;
	str.append(to_string(this->id) + "\t(" + to_string(this->word) + "," + to_string(this->bitKey) + ")\t" + this->type + "\n\tNG SET: ");
	for (int i = 0; i < this->ngSet.size(); i++) {
		str.append(to_string(this->ngSet.at(i)) + " ");
	}
	if (printAdjacencyLists) {
		str.append("\n\tIN GOING: ");
		for (unordered_map<int, int>::const_iterator it = this->inGoingArcs.begin(); it != this->inGoingArcs.end(); it++) {
			str.append("(" + to_string(it->first) + "," + to_string(it->second) + ") ");
		}
		str.append("\n\tOUT GOING: ");
		for (unordered_map<int, int>::const_iterator it = this->outGoingArcs.begin(); it != this->outGoingArcs.end(); it++) {
			str.append("(" + to_string(it->first) + "," + to_string(it->second) + ") ");
		}
		str.append("\n\tEXT. PREC.: ");
		for (int i = 0; i < this->extendedPredecessors.size(); i++) {
			str.append(to_string(this->extendedPredecessors.at(i)) + " ");
		}
	}
	return str;
}
