#include "ArcnetBusDelay.h"

namespace cosi {

namespace models {

namespace wiredbas {

ArcnetBusDelay::ArcnetBusDelay(double pBusSpeed,
		cosi::models::wiredbas::WireDelay* pWireDelay) {
	mBusSpeed = pBusSpeed ;
	mMsgLength[IIT] = 39;
	mMsgLength[FBE ] = 39;
	mMsgLength[ACK ] = 17;
	mMsgLength[SPAC] = 94;
	mMsgLength[LPAC] = 105;
	//Sum n*11 for a message of length n bytes.
	mWireDelay = pWireDelay ;
}

ArcnetBusDelay::~ArcnetBusDelay() {
}

void ArcnetBusDelay::SetWireDelayModel(
		cosi::models::wiredbas::WireDelay* pWireDelay) {
	mWireDelay = pWireDelay ;
}

RealDelay ArcnetBusDelay::Get(cosi::commstruct::wiredbas::Implementation pC) {
	return RealDelay(GetValue(pC)) ;
}

RealDelay ArcnetBusDelay::Get(cosi::commstruct::wiredbas::Implementation* pC) {
	return RealDelay(GetValue(pC)) ;
}

double ArcnetBusDelay::GetValue(cosi::commstruct::wiredbas::Implementation pC) {
	return GetValue(&pC) ;
}

double ArcnetBusDelay::GetValue(cosi::commstruct::wiredbas::Implementation* pC) {

	//do not consider wiring delay that are indeed negligible.
	IdGraph::v_iterator U;
	int Nbits = 0;
	for (U = pC->v_begin() ; U != pC->v_end() ; U++) {
		//If it is a destination only add the IIT
		if ( ( (*pC)[*U].PRJ(ThreadSet)Size() == 0) ) {
			Nbits += mMsgLength[IIT];
		}
		else if ( ((*pC)[*U].PRJ(ThreadSet)GetLongestMessage()).GetMessageLength() == 0 ) {
			Nbits += mMsgLength[IIT];
		}
		else {
			Nbits += ComputeMessageLength( ((*pC)[*U].PRJ(ThreadSet)GetLongestMessage()).GetMessageLength());
		}
	}
	return (Nbits/mBusSpeed);
}

int ArcnetBusDelay::ComputeMessageLength(int pBits) {
	int RetVal = 0;
	RetVal+= mMsgLength[IIT] + mMsgLength[FBE]+ 2*mMsgLength[ACK];

	int Bytes;
	if (pBits%8== 0)
		Bytes = pBits/8;
	else
		Bytes = pBits/8+ 1;
	RetVal += 11*Bytes ;
	//check if it is a short packet or a long packet
	if (Bytes <= 256) {
		RetVal+= mMsgLength[ SPAC ];
	} else {
		RetVal += mMsgLength[ LPAC ];
	}

	return RetVal ;
}

}

}

}
