/************************************************************/
/*                                                          */
/*  The cpp file of receiver program                        */
/*  For CS 145 (Fall 2003) Lab 2                            */
/*  Author: Xiaoliang (David) Wei                           */
/*  Date:   Nov 07, 2002                                    */
/*                                                          */
/************************************************************/


/*
Command Line format:
receiver <number of packet> <packetsize> <filename> 

Note:
1. The algorithm for packet re-assembly:
     This program and the sender define the seq# of the first packet as 1 and the seq # is increasingly sequential integer. 
     Taking the advantage of such definition of seq#, the algorithm uses index sort to reassemble the packets. The program first reads all the packets "received", and write each packet to another file according to the packet's seq# (The new file starts with "S" instead of "P"). The filename of "S" files are "correct". Then the program read the S files in order and output the packets to the file. 
     Space complexity: O(n) where n is the file size
     Time complexity: O(n) 
 
2. This program will generate additional temp file starting with "S". That is: S0000001, S0000002...
These tmp files should be removed before running this program.
*/


#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "udpfile.h"


FILE *outfile; //Input file. 

u_int32_t packetSize;
u_int32_t fileSize=0;
u_int32_t pktNum;

int main (int argc,char *argv[])
{

	if (argc!=4)
	{
		printf("Error: Format of this command should be: receiver <number of packet> <packetsize> <filename> \n");
		return 1;
	}
	pktNum=atoi(argv[1]);
	packetSize=atoi(argv[2]);


//Open the targer file 	
	outfile=fopen(argv[3],"w");
	if (outfile==NULL)
	{
		printf("Erorr when writing to the file %s!\n",argv[3]);
		return 1;
	}
	
	
	//this part read the packets one by one into the memory, and save to another file (starting with "S") according to the seq number
	for (int i=1;i<=pktNum;i++)
	{
		char filename[100];
		sprintf(filename,"%lu.txt",10000000+i);
		filename[0]='P';
		
		FILE * pktfile=fopen(filename,"r");
		if (pktfile==NULL)
			printf("Error: cannot open the packet file %s\n",filename);
		else
		{
			// read the packet from file			
			Packet *p=new Packet(pktfile);
			fclose(pktfile);
			
			// save to another file
			p->send_to_file('S');
			if (p->size>packetSize)
			{
				printf("Warning: the actual packet size is larger than the maximum size provided by parameter\n");
			}
			
			if (fileSize==0)
			{
	                        //save the file size
				fileSize=p->getHeaderPtr()->tt_seq;
			}
			else
			if (fileSize!=(p->getHeaderPtr()->tt_seq))
			{
				//find inconsistency in different packets.
				printf("Warning: two packets give inconsistent file size in packet!\n");
			}
			delete p;
		}
	}
	
	
	//reassemble the original stream
	for (int i=1;i<=fileSize;i++)
	{
		char filename[100];
		sprintf(filename,"%lu.txt",10000000+i);
		filename[0]='S';
		
		FILE * pktfile=fopen(filename,"r");
		if (pktfile==NULL)
			//No such packet: this packet is missing.
			fprintf(outfile,"#");
		else
		{
			// got this packet. output to the file. 
			Packet *p=new Packet(pktfile);
			fclose(pktfile);

			//write to target file
			p->output(outfile);
			delete p;
		}		
	}
	fclose(outfile);
};


