#include "FEPClient.h"

/**
 * Constructor
 * 
 * @param host The host rpc server ip address
 * @param networkFile the xml network file
 */
FEPClient::FEPClient(char * host, char * networkFile)
{
	createClient(host);
	networkReader = new NetworkReader(networkFile);
	updateATMS();
}

/**
 * Destructor
 */
FEPClient::~FEPClient()
{
	cout << "Destroying client..." << endl;
	clnt_destroy(clnt);
}

/**
 * Handler for the ATMS RPC Response (to the client RPC Call)
 * @param response pointer to fep_reply struct
 */
void FEPClient::handleCallResponse(void *response)
{
	/* If ATMS reply call fails */
	if (response == NULL)
	{
		clnt_perror(clnt, "RPC call failed");
	}
	/* If ATMS reply is successful */
	else
	{
		cout << "Successful RPC call to ATMS..." << endl;
	}
}

/**
 * Sends an fep_reply for every line in the FEP.
 */
void FEPClient::updateATMS()
{
	int i, j; // i == line_index, j == lds_index
	void *rv;

    vector<FEP_LINE> lines = networkReader->getLines();
    vector<LDS_LOOP> ldsMap = networkReader->getStations();

	// Send one reply for every "line" in the FEP
	for (i = 0; i < lines.size(); i++)
	{
		fep_reply  fepReply;
                cout << "Sending fepReply for line #" << lines.at(i).lineNum << endl;
		// populate reply
		fepReply.reply = SHORTPOLL;
		fepReply.schedule = lines.at(i).schedule;
		fepReply.lineinfo = lines.at(i).lineInfo;
		fepReply.kind = (enum polltype) 0;
		fepReply.flag = (enum replykind) 0;

		/***********************************
			 This is an update to an extern, this should happen on the Java driver side??
		lines.at(i).schedleSeq += 1;
		lines.at(i).globalSeq += 51;
		*/

		fepReply.schedule_sequence = lines.at(i).schedleSeq;
		fepReply.global_sequence = lines.at(i).globalSeq;
		/************************************
			 Need to find out what appropriate schedule time is: look at uci_unix_simulation_time src code
		fepReply.schedule_time =
			uci_unix_simulation_time(uci_simulation_time());	// GMT time
		*/
		fepReply.schedule_time = time(NULL);

		fepReply.user_info1 = lines.at(i).lineNum;
		fepReply.user_info2 = lines.at(i).lineNum;
		fepReply.system_key = lines.at(i).systemKey;

		fepReply.answers.size = 1;
		fepReply.answers.fep_answer_list_u.shortp.count = 1;

		/* for each LDS in the Line.... (constructs the short_answer message) */
		for (j = 0; j < lines.at(i).lds.size(); j++)
		{
			fep_shortanswer fsa;
			int index = lines.at(i).ldsIndex.at(j);
                        cout << "LDS index: " << index << endl;
			// msg: oa, od, ldsMap.at(index).dataPack, od, ff
			fsa.msg.message_len = ldsMap.at(index).length + 2;
			fsa.msg.message[0] = 0x0d;
			fsa.msg.message[1] = 0x0a;
			for (int k = 0; k < ldsMap.at(index).length; k++)
				fsa.msg.message[2 + k]	= ldsMap.at(index).dataPack[k];
			int aa = ldsMap.at(index).length;
			fsa.msg.message[2 + aa] = 0x0d;
			fsa.msg.message[3 + aa] = 0xff;	//????????????? warning ?????

			// info
			fsa.info.poll_error_count = 0;
			/***************************************
				 Need to find out polltime uci time function src code
			fsa.info.poll_time = uci_unix_simulation_time(uci_simulation_time());
			*/
			fsa.info.poll_user_info1 = ldsMap.at(index).drop;	// drop number
			fsa.info.poll_user_info2 = 1;	//always 1
			fsa.info.retries = 0;
			fsa.info.status = (enum replystatus) 1;

			//fepReply.answers.fep_answer_list_u.shortp.answers[j] = fsa;
			fepReply.answers.fep_answer_list_u.shortp.answers[0] = fsa;

			// send out data
			printf("Transferring line=%d, lds_drop_no=%d...\n", lines.at(i).lineNum, ldsMap.at(index).drop);
			rv = fep_reply_xfer_32(&fepReply, clnt);

			/* Handle ATMS response to RPC Call */
			printf("Handling ATMS response...\n");
			handleCallResponse(rv);
		}
	}
}

/**
 * Creates the RPC Client. If not successful, exit with status 1.
 * @param host rpc server ip
 */
void FEPClient::createClient(char * host)
{
	/* Create RPC Client to communicate with ATMS */
	cout << "Creating RPC Client" << endl;
	clnt = clnt_create(host, /*100090,*/ 103121, 32, "tcp");
        cout << "Client created" << endl;
	/* Check if client creation failed */
	if (clnt == (CLIENT *) NULL)
	{
		cerr << "Can't create client to " << host << endl;
		exit(1);
	}
}

/**
 * Main driver for ATMSCommunicator. Creates an RPC Client from command line args.
 * @param argc
 * @param argv
 * @return 
 */
int main(int argc, char *argv[]) {

	char *host;
	char *networkFile;

	if (argc < 3)
	{
		cout << "usage:  " << argv[0] << " server_host networkFile" << endl;
		exit(1);
	}

	/* Create RPC Client to send an fep_reply to ATMS */
	host = argv[1];
        networkFile = argv[2];

	FEPClient *client = new FEPClient(host, networkFile);
        delete client;

	return 0;
}
