#include "NetworkReader.h"

// Constructor
NetworkReader::NetworkReader(string networkFile)
{
    this->networkFile = networkFile;
}

// determine if a loop has data based on lane config data
bool NetworkReader::DataAvail(char flag, int num)
{
	int mag, fel;

	// find mask value
	if (num == 1)
		mag = 0x01;
	else if (num == 2)
		mag = 0x02;
	else if (num == 3)
		mag = 0x04;
	else if (num == 4)
		mag = 0x08;
	else if (num == 5)
		mag = 0x10;
	else if (num == 6)
		mag = 0x20;
	else if (num == 7)
		mag = 0x40;
	else if (num == 8)
		mag = 0x80;

	fel = flag & mag;
	fel = fel >> (num - 1);

	if (fel == 1)
		return true;
	else
		return false;
}

// Initializes the LDS_LOOP dataPack with all necessary static data and default dynamic data
unsigned char * NetworkReader::msgDataPack(LDS_LOOP loop)
{
	int j;
	// Allocate memory for dataPack
	unsigned char *dataPack = (unsigned char *) malloc(sizeof(unsigned char) * loop.length);

	// dataPack 5-8: lane config
	char d5 = 0, d6 = 0, d7 = 0, d8 = 0;
	for (j = 0; j < loop.num; j++)
	{
		for (int k = 0; k < 8; k++)
		{
			if (strcmp(loop.loop_loc[j], dp5[k]) == 0)
				d5 += pow(2, k);
			if (strcmp(loop.loop_loc[j], dp6[k]) == 0)
				d6 += pow(2, k);
			if (strcmp(loop.loop_loc[j], dp7[k]) == 0)
				d7 += pow(2, k);
			if (strcmp(loop.loop_loc[j], dp8[k]) == 0)
				d8 += pow(2, k);
		}
	}
	dataPack[5-1] = d5;
	dataPack[6-1] = d6;
	dataPack[7-1] = d7;
	dataPack[8-1] = d8;

	// dataPack 1: Drop number, i.e. station address
	dataPack[1-1] = loop.drop;

	// dataPack2 (2 bytes per loop)
	dataPack[2-1] = loop.num * 2 + Fixed_Byte_To_Checksum;

	// dataPacket 3 (lowbyte: # of mainline loops, highbyte: # of opposite loops)
	int low = 0, high = 0;
	for (j = 1; j <= 6; j++)
	{
		low += DataAvail(dataPack[5-1], j);
		high += DataAvail(dataPack[6-1], j);
	}
	high = high << 4;
	dataPack[3-1] = high | low;

	// dataPack4 (Miscl. flags: samples are: 80, A0, E0, 00)
	dataPack[4-1] = 0xA0;

	// dataPack 9: initialized as 00 (meaning no metering); need to be updated every 30 sec
	dataPack[9-1] = 0;

	// datadataPack 10-13: lane malfunction? Assuming all functional
	dataPack[10-1] = 0;
	dataPack[11-1] = 0;
	dataPack[12-1] = 0;
	dataPack[13-1] = 0;

	// dataPack 14-22: ramp metering data
	// BYTE 16 and 22 need to be updated every 30 sec
	bool found = false;
	for (j = 0; j < loop.num; j++)
	{
		if (strcmp(loop.loop_loc[j], "DEMAND") == 0)
		{
			found = true;
			break;
		}
	}
	if (found)
	{
		// BYTE 14: mostly 07, some are 05, 03, 00
		dataPack[14-1] = 0x07;
		// mostly 06(TOD table 1); some are 0B (No metering) or 05(traffic responsive)
		dataPack[15-1] = 0x06;
		// most 00, some are 01 (queue override) or 80(Meter ON sign)
		dataPack[16-1] = 0x00;
		// Field Manual Rate
		dataPack[17-1] = 0xFF;
		// TOC Manual Rate
		dataPack[18-1] = 0xFF;
		// PSO Manual Rate
		dataPack[19-1] = 0xFF;
		// CORM Rate
		dataPack[20-1] = 0xFF;
		// Local Responsive Rate. DON'T UNDERSTAND YET
		dataPack[21-1] = 0x00;
		// TOD Rate: need to query RAMP plugin!
		dataPack[22-1] = 0x00;
	}
	// LDS: NO Metering
	else
	{
		dataPack[14-1] = 0x00;
		dataPack[15-1] = 0x0B;
		dataPack[16-1] = 0x00;
		dataPack[17-1] = 0xFF;
		dataPack[18-1] = 0xFF;
		dataPack[19-1] = 0xFF;
		dataPack[20-1] = 0xFF;
		dataPack[21-1] = 0x00;
		dataPack[22-1] = 0x00;
	}

	// dataPack 23-24: sum of mainline/Oppsite traffic data; need to be updated every 30 sec
	loop.MlTotVol = 0;
	loop.OppTotVol = 0;
	dataPack[23-1] = loop.MlTotVol;
	dataPack[24-1] = loop.OppTotVol;

	// dataPack 25-26: BYTE 25 is fixed, i.e. 03; BYTE 26 is either 0xA2 or 0x84
	dataPack[25-1] = 0x03;
	dataPack[26-1] = 0x84;

	/* printf("lds=%d (%d), p1=%2X, p2=%2X, p3=%2X, p5=%2X, p6=%X, p7=%X, p8=%2X\n",
		loop.lds, loop.length, dataPack[1-1], dataPack[2-1],
		dataPack[3-1], dataPack[5-1],
		dataPack[6-1], dataPack[7-1], dataPack[8-1]);
    */
	return dataPack;
}

// TEST DATA
// lds_id	line 	drop sch lineinfo	system_key	sch_seq glo_seq		count	freeway	Dir	ca_pm	lds_name
// 1208926	29	4	28	28	1123006080	26480	1357609		13	73	S	23.7	MACARTHUR 1
vector<FEP_LINE> NetworkReader::getLines()
{
	vector<FEP_LINE> lines;
	FEP_LINE line;
	line.lineNum = 29;
	line.lds.push_back(1208926);
	line.ldsIndex.push_back(0);
	line.ldsNum = 1;
	line.count = 13;
	line.schedule = 28;
	line.globalSeq = 1357609;
	line.schedleSeq = 26480;

	lines.push_back(line);
	return lines;
}

// TEST DATA
//FWY	Dir     POSTMI	LDS_ID	VDS_ID	LOOP_ID LOC    LANE LOOP_LOC      	PARAMICS_NAME  PARAMICS_LANE
//73	S	23.7	1208926	1210494	1210490	ML	1	ML_1       	?            	0
//73	S	23.7	1208926	1210494	1210492	ML	2	ML_2       	?            	0
//73	S	23.7	1208926	1210494	1210493	ML	3	ML_3       	?            	0
//73	S	23.7	1208926	1210770	1210769	OR	1	RAMP_ON    	?            	0
vector<LDS_LOOP> NetworkReader::getLoops()
{
	/* Read loop meta data */
	vector<LDS_LOOP> lds_map;
	LDS_LOOP loop;

	loop.lds = 1208926;
	loop.line_num = 29;
	loop.drop = 4;
	loop.num = 4;

	// Loop ids
	long *loopIDs = (long *) calloc(sizeof(long), loop.num);
	loopIDs[0] = 1210490;
	loopIDs[1] = 1210492;
	loopIDs[2] = 1210493;
	loopIDs[3] = 1210769;
	loop.loopID = loopIDs;

	// Loop locations
	char *one = "ML_1";
	char *two = "ML_2";
	char *three = "ML_3";
	char *four = "RAMP_ON";
	char **loc = (char **) calloc(sizeof(char *), loop.num);
	loc[0] = one;
	loc[1] = two;
	loc[2] = three;
	loc[3] = four;
	loop.loop_loc = loc;

	// Data pack ATMS message
	loop.length = loop.num * 2 + CONTROL_DATA_LEN;
 	loop.dataPack = msgDataPack(loop);

	loop.pos = 0;

	loop.MlTotVol = 0;
	loop.OppTotVol = 0;

	lds_map.push_back(loop);
	return lds_map;
}
