#include "node.h"
#include "radius.h"

unsigned char getTxHashFn(const void* ps){
WifiPair* pair = (WifiPair*)ps;
return pair->tx.mac.str[5];
}

unsigned char getRxHashFn(const void* ps){
WifiPair* pair = (WifiPair*)ps;
return pair->rx.mac.str[5];
}

int isEqTx(const void* pt, const void* ps){
WifiPair* p1 = (WifiPair*)pt;
WifiPair* p2 = (WifiPair*)ps;
	if( p1->tx.mac.adr == p2->tx.mac.adr )
		return 0;
return 1;
}

int isEqRx(const void* pt, const void* ps){
WifiPair* p1 = (WifiPair*)pt;
WifiPair* p2 = (WifiPair*)ps;
	if( p1->rx.mac.adr == p2->rx.mac.adr )
		return 0;
return 1;
}

int isEqTxRx(const void* pt, const void* ps){
WifiPair* p1 = (WifiPair*)pt;
WifiPair* p2 = (WifiPair*)ps;
	if( p1->tx.mac.adr == p2->tx.mac.adr &&
	    p1->rx.mac.adr == p2->rx.mac.adr )
		return 0;
return 1;
}


int isEqRxType(const void* pt, const void* ps){
WifiPair* p1 = (WifiPair*)pt;
WifiPair* p2 = (WifiPair*)ps;
        if( p1->rx.mac.adr == p2->rx.mac.adr
	    && p1->type & p2->type )
		return 0;
return 1;
}

int isEqTxType(const void* pt, const void* ps){
WifiPair* p1 = (WifiPair*)pt;
WifiPair* p2 = (WifiPair*)ps;
        if( p1->tx.mac.adr == p2->tx.mac.adr
	    && p1->type & p2->type )
		return 0;
return 1;
}


int isEqTxTime(const void* pt, const void* ps){
WifiPair* p1 = (WifiPair*)pt;
WifiPair* p2 = (WifiPair*)ps;
	if( p1->tx.mac.adr == p2->tx.mac.adr && p1->time == p2->time )
		return 0;
return 1;
}


int isEqTxRxTime(const void* pt, const void* ps){
WifiPair* p1 = (WifiPair*)pt;
WifiPair* p2 = (WifiPair*)ps;
	if( p1->tx.mac.adr == p2->tx.mac.adr && 
	    p1->rx.mac.adr == p2->rx.mac.adr && 
	    p1->time == p2->time )
		return 0;
return 1;
}


int isEqRxTime(const void* pt, const void* ps){
WifiPair* p1 = (WifiPair*)pt;
WifiPair* p2 = (WifiPair*)ps;
	if( p1->rx.mac.adr == p2->rx.mac.adr && p1->time == p2->time )
		return 0;
return 1;
}

int isEqType(const void* pt, const void* ps){
WifiPair* p1 = (WifiPair*)pt;
WifiPair* p2 = (WifiPair*)ps;
	if( p1->type & p2->type )
		return 0;
return 1;
}

int isEqTypeNoSelf(const void* pt, const void* ps){
WifiPair* p1 = (WifiPair*)pt;
WifiPair* p2 = (WifiPair*)ps;
	if( p1->type & p2->type )
		if( p1->time != p2->time || 
		p1->tx.mac.adr != p2->tx.mac.adr || 
		p1->rx.mac.adr != p2->rx.mac.adr )
			return 0;
return 1;
}

void* newWifiPair(){
WifiPair *pair = calloc(1, sizeof(WifiPair));

 pair->rx.Gain = 1; 
 pair->tx.Gain = 1; 
 
 return pair;
}

void* newWifiPairCur(){
WifiPair *pair = calloc(1, sizeof(WifiPair));

 pair->rx.Gain = 1; 
 pair->tx.Gain = 1; 

 pair->type = C_SIGNAL;
 
/* to make sure that after cctor..Cur the posS will be 0 */ 
 pair->posS = -1; 

 return pair;
}


void ctorWifiPair(void* pt, const void* ps){
int i;
WifiPair* pTrg = (WifiPair*)pt;
WifiPair* pSrc = (WifiPair*)ps;

	memcpy(pTrg, pSrc, sizeof(WifiPair));

}

void ctorWifiPairCur(void* pt, const void* ps){
int i;
WifiPair* pTrg = (WifiPair*)pt;
WifiPair* pSrc = (WifiPair*)ps;

	memcpy(&pTrg->rx, &pSrc->rx, sizeof(WifiNode));
	memcpy(&pTrg->tx, &pSrc->tx, sizeof(WifiNode));

	/* Asigning cycle buffer S */
	pTrg->posS = (pTrg->posS + 1) % MAX_S_NUM;
	pTrg->Sarr[pTrg->posS] = pSrc->S;
	pTrg->numS = pTrg->numS < MAX_S_NUM ? (pTrg->numS+1) : MAX_S_NUM;

	if( pTrg->type & C_NPOW )
	  pTrg->Rarr[pTrg->posS] = RcalcN(pTrg);
	else
	  pTrg->Rarr[pTrg->posS] = 0.;
	pTrg->numRcalc = pTrg->numS;

	/* calculate the mean signal strenth */
	pTrg->S = 0;
	pTrg->Rcalc = 0;
	for( i=0; i<pTrg->numS; ++i ){
		pTrg->S += pTrg->Sarr[i];
		pTrg->Rcalc += pTrg->Rarr[i];
	}
	pTrg->S /= pTrg->numS;
	pTrg->Rcalc /= pTrg->numRcalc;
	
	/* calculate the mean signal deviation */
	pTrg->sigmaS = 0.;
	pTrg->sigmaRcalc = 0.;
	for( i=0; i<pTrg->numS; ++i ){
	  pTrg->sigmaS = (pTrg->S - pTrg->Sarr[i])*(pTrg->S - pTrg->Sarr[i]);
	  pTrg->sigmaRcalc = (pTrg->Rcalc - pTrg->Rarr[i])*(pTrg->Rcalc - pTrg->Rarr[i]);
	}
	pTrg->sigmaS = sqrt( pTrg->sigmaS / pTrg->numS );
	pTrg->sigmaRcalc = sqrt( pTrg->sigmaRcalc / pTrg->numRcalc );

	pTrg->time = time(NULL);

}

void ctorWifiPairLoad(void* pt, const void* ps){
WifiPair* pTrg = (WifiPair*)pt;
WifiPair* pSrc = (WifiPair*)ps;

	memcpy(pTrg, pSrc, sizeof(WifiPair));

	/* Calculate a distance if locations of both piers are known and the distance is not yet calculated */
	if( (pTrg->type & C_TXYZ) && (pTrg->type & C_RXYZ) && !(pTrg->type & C_RADIUS) ){
		pTrg->type |= C_RADIUS;
		pTrg->R = sqrt( 
			(pTrg->tx.X - pTrg->rx.X) * (pTrg->tx.X - pTrg->rx.X)+
			(pTrg->tx.Y - pTrg->rx.Y) * (pTrg->tx.Y - pTrg->rx.Y)+
			(pTrg->tx.Z - pTrg->rx.Z) * (pTrg->tx.Z - pTrg->rx.Z));
		pTrg->numR = 1;
	}

	/* Make old measurements less influential on the new mean */ 
	pTrg->numS = 1;
	pTrg->posS = 0;
	pTrg->Sarr[0] = pTrg->S;
	pTrg->Rarr[0] = pTrg->Rcalc;
}
