#include "PlatformInstance.h"

namespace cosi {

namespace commstruct {

namespace onchipcommunication {

PlatformInstance::PlatformInstance(std::string pName) :
	CommunicationStructure<PlatformLabel>(pName) {
}

PlatformInstance::~PlatformInstance() {
}

PlatformInstance PlatformInstance::operator+(PlatformInstance pC) {
	PlatformInstance RetVal("");
	IdGraph::v_iterator U , V;
	for( U = this->v_begin(); U != this->v_end();U++) {
		RetVal.AddVertex(*U);
		RetVal.SetName(*U,GetName(*U));
		if ( pC.InV(*U)) {
			RetVal[*U].PRJ(Name)Set((*this)[*U].PRJ(Name)Get() - pC[*U].PRJ(Name)Get());
			RetVal[*U].PRJ(Type)Set((*this)[*U].PRJ(Type)Get() - pC[*U].PRJ(Type)Get());
			RetVal[*U].PRJ(NodeParameter)Set((*this)[*U].PRJ(NodeParameter)Get() - pC[*U].PRJ(NodeParameter)Get());
			//take the superset
			if ( ! ((*this)[*U].PRJ(Ports)Get() - pC[*U].PRJ(Ports)Get() == pC[*U].PRJ(Ports)Get()) &&
					! ((*this)[*U].PRJ(Ports)Get() - pC[*U].PRJ(Ports)Get() == (*this)[*U].PRJ(Ports)Get()) ) {
				RetVal[*U].PRJ(Ports)Set(cosi::quantity::onchipcommunication::Ports());
			} else {
				RetVal[*U].PRJ(Ports)Set((*this)[*U].PRJ(Ports)Get() + pC[*U].PRJ(Ports)Get());
			}
			RetVal[*U].PRJ(Position)Set((*this)[*U].PRJ(Position)Get() - pC[*U].PRJ(Position)Get());
			RetVal[*U].PRJ(IpGeometry)Set((*this)[*U].PRJ(IpGeometry)Get() + pC[*U].PRJ(IpGeometry)Get());
		} else {
			RetVal[*U].PRJ(Name)Set((*this)[*U].PRJ(Name)Get());
			RetVal[*U].PRJ(Type)Set((*this)[*U].PRJ(Type)Get());
			RetVal[*U].PRJ(Ports)Set((*this)[*U].PRJ(Ports)Get());
			RetVal[*U].PRJ(Position)Set((*this)[*U].PRJ(Position)Get());
			RetVal[*U].PRJ(IpGeometry)Set((*this)[*U].PRJ(IpGeometry)Get());
			RetVal[*U].PRJ(NodeParameter)Set((*this)[*U].PRJ(NodeParameter)Get());
		}

	}

	for( V = pC.v_begin(); V != pC.v_end();V++) {
		if ( ! InV(*V)) {
			RetVal.AddVertex(*V);
			RetVal.SetName(*V,pC.GetName(*V));
			RetVal[*V].PRJ(Name)Set(pC[*V].PRJ(Name)Get());
			RetVal[*V].PRJ(Type)Set(pC[*V].PRJ(Type)Get());
			RetVal[*V].PRJ(Ports)Set(pC[*V].PRJ(Ports)Get());
			RetVal[*V].PRJ(Position)Set(pC[*V].PRJ(Position)Get());
			RetVal[*V].PRJ(IpGeometry)Set(pC[*V].PRJ(IpGeometry)Get());
			RetVal[*V].PRJ(NodeParameter)Set(pC[*V].PRJ(NodeParameter)Get());
		}
	}

	for( U = this->v_begin(); U != this->v_end();U++) {
		for( V = this->v_begin(); V != this->v_end();V++) {
			if ( InE(*U,*V)) {
				RetVal.AddEdge(*U,*V);
				Edge E(*U,*V);
				if ( pC.InE(*U,*V)) {
					RetVal[E].PRJ(LinkParameter)Set((*this)[E].PRJ(LinkParameter)Get() - pC[E].PRJ(LinkParameter)Get());
					RetVal[E].PRJ(WiringPath)Set((*this)[E].PRJ(WiringPath)Get() - pC[E].PRJ(WiringPath)Get());
				} else {
					RetVal[E].PRJ(LinkParameter)Set((*this)[E].PRJ(LinkParameter)Get() );
					RetVal[E].PRJ(WiringPath)Set((*this)[E].PRJ(WiringPath)Get() );
				}

			}
		}
	}

	for( U = pC.v_begin(); U != pC.v_end();U++) {
		for( V = pC.v_begin(); V != pC.v_end();V++) {
			if ( ! InE(*U,*V) && pC.InE(*U,*V)) {
				Edge E(*U,*V);
				RetVal.AddEdge(*U,*V);
				RetVal[E].PRJ(LinkParameter)Set(pC[E].PRJ(LinkParameter)Get() );
				RetVal[E].PRJ(WiringPath)Set(pC[E].PRJ(WiringPath)Get() );
			}
		}
	}

	return RetVal;
}

}

}

}
