/**********************************************************************
   FS.C
   Z-World, 2001
  
   This program will contact the DevMate and upload to it
   some files, that will be made avaliable as a web page. The
   complimentary file, FS.C in the samples\dmunit directory
   should be used on the DevMate, to give this program something
   to talk to.
  
   As this program demonstrates all of the filesystem functions
   available, it should not be run straight-through like normal.
   After the DevMate program is running, load this one on
   the target and insert a few breakpoints, where they are marked
   below. It can then be run to the breakpoints, and while it is
   stopped, different results can be seen on the web server.
  
   When comparing the different results on the web server, it is
   important to remember to do a full-refresh (shift-refresh in
   most browsers) such that the browser's internal cache is not
   relied upon. 
**********************************************************************/

/*
 * get some sample data to send
 */
#ximport "samples/tcpip/http/pages/static.html"    index_html
#ximport "samples/tcpip/http/pages/rabbit1.gif"    rabbit1_gif

/*
 * Define this to format the FS on the DevMate. This may not work
 * if another service, such as logging, has a file open on the DevMate!
 */
//#define FORMAT

/*
 * Turn on debug messages, if this is uncommented
 */
//#define TC_FS_DEBUG

/*
 * Select the filesystem support
 */
#define USE_TC_FS

/*
 * Uncomment this line if this program will be loaded over ethernet. This will
 * force the DevMate communication to use serial port A, re-using the programming
 * link that was used to download the program.
 */
//#define USE_TC_LOADER

#use "tc_conf.lib"

/*
 * the file pointer that will be used in all commands to the DevMate
 */
DMFile file;

/*
 * Send a file to the DevMate, and
 * return it's file ID
 */
int send_file(long data, char *name)
{
	auto int retval;
	auto long big_len;
	auto int length, offset, writesize;
#define SEND_FILE_BUFSIZE	64
	/* "dcrtcp.lib" also defines "BUFSIZE", so choose private name. */
	auto char buf[SEND_FILE_BUFSIZE];
	auto FNumber id;

	/* find the length of the */
	if(xmem2root((char *)&big_len, data, 4)) {
		// error
		exit(1);
	}
	printf("Opening file '%s'...\n",name);

	/* open the file */
	while(TC_PENDING == (retval = devmate_fs_open(&file, 0, name, TC_FS_FLAGS_NEWID)))
		devmate_tick();
	if(TC_SUCCESS != retval) {
		// error
		exit(2);
	}

	printf("Sending the file...\n");

	/* send the file */
	length = (int)big_len;
	offset = 0;
	
	while(offset < length) {
		writesize = length - offset;
		if(writesize > SEND_FILE_BUFSIZE)
			writesize = SEND_FILE_BUFSIZE;

		/* get one block of data */
		if(xmem2root(buf, data + 4 + offset, writesize)) {
			// error
			exit(3);
		}

		/* send that block to the target */
		retval = devmate_fs_append(&file, buf, writesize);
		if(-1 == retval) {
			// error! transaction is cancled!
			exit(4);
		}
		offset += retval;

		/* drive the communications */
		devmate_tick();
	}

	printf("Send complete - closing the file...\n");

	/* file is written - close it all! */
	while(TC_PENDING == (retval = devmate_fs_close(&file,&id)))
		devmate_tick();

	if(TC_SUCCESS != retval) {
		// error
		exit(5);
	}

	printf("File '%s' sent correctly!\n",name);

	/* return the id of the created file */
	return id;
#undef SEND_FILE_BUFSIZE
}

void main(void)
{
	int rv;
	long	timeout;
	FNumber index_file, logo_file, test_id;

	/*
	 * Standard initialization
	 */	
	devmate_init();

	/*
	 * Sync with the target
	 */
resync:
	timeout = MS_TIMER + 2000; // wait two seconds
#ifdef FORMAT
	while(TC_PENDING != devmate_fs_sync(&file,TC_FS_FORMAT)) {
#else
	while(TC_PENDING != devmate_fs_sync(&file,0)) {
#endif
		devmate_tick();
	}
	while(TC_PENDING == (rv = devmate_fs_finish(&file))) {
		if(MS_TIMER > timeout) {
			// timeout - the sync packets should be resent
			// automagicly, but let's start it again anyway
			goto resync;
		}
		devmate_tick();
	}
	if(TC_SUCCESS != rv) {
		printf("Error in init!\n");
		exit(-1);
	} else {
		printf("INIT was successfull!\n");
	}

	/*
	 * Send some data
	 */
	index_file = send_file(index_html,"/index.html");
	logo_file = send_file(rabbit1_gif,"/rabbit1.gif");

	/*********************************************
	 * ===---> INSERT A BREAKPOINT HERE! <---=== *
	 * Browse to "[ip_address]/index.html" to    *
	 * see the pages that were uploaded.         *
	 *********************************************/
	; // breakpoint handle

	/*
	 * Delete foo.html if it exists
	 */
	test_id = -1;
tryagain_foolookup:
	switch(devmate_fs_idlookup(&file,"/foo.html",&test_id)) {
	case TC_PENDING:
		/* finish the idlookup */
		while(TC_PENDING == (rv = devmate_fs_finish(&file)))
			devmate_tick();
		if(TC_SUCCESS == rv)
			break;
		/* fall through */
	case TC_ERROR:
		/* file doesn't exist */
		break;
	case TC_SUCCESS:
		break;
	}
	if(test_id != -1) {
		/* need to erase the file */
tryagain_foodelete:
		switch(devmate_fs_delete(&file,test_id)) {
		case TC_PENDING:
			/* finish the delete */
			while(TC_PENDING == (rv = devmate_fs_finish(&file)))
				devmate_tick();
			if(TC_SUCCESS == rv)
				break;
			/* fall through to the error state */
		case TC_ERROR:
			devmate_tick();
			goto tryagain_foodelete;
		case TC_SUCCESS:
			break;
		}
	}

	/*
	 * Rename the index file
	 */
	printf("Renaming '/index.html' to '/foo.html'... ");
tryagain_rename:
	switch(devmate_fs_rename(&file,index_file,"/foo.html")) {
	case TC_PENDING:
		/* finish the rename */
		while(TC_PENDING == (rv = devmate_fs_finish(&file)))
			devmate_tick();
		if(TC_SUCCESS == rv)
			break;
		/* fall through to the error state */
	case TC_ERROR:
		devmate_tick();
		goto tryagain_rename;
	case TC_SUCCESS:
		/* success! - do nothing */
		break;
	}
	printf("Done!\n");

	/*********************************************
	 * ===---> INSERT A BREAKPOINT HERE! <---=== *
	 * Browse to "[ip_address]/foo.html" to      *
	 * see the page as it is renamed.            *
	 *********************************************/
	; // breakpoint handle

	/*
	 * Verify the ID of the gif - it should match what we
	 * know it to be.
	 */
	printf("Looking up the file-ID of '/rabbit1.gif'... ");
	test_id = -1;
tryagain_idlookup:
	switch(devmate_fs_idlookup(&file,"/rabbit1.gif",&test_id)) {
	case TC_PENDING:
		/* finish the idlookup */
		while(TC_PENDING == (rv = devmate_fs_finish(&file)))
			devmate_tick();
		if(TC_SUCCESS == rv)
			break;
		/* fall through to the error state */
	case TC_ERROR:
		devmate_tick();
		goto tryagain_idlookup;
	case TC_SUCCESS:
		break;
	}
	if(test_id == logo_file) {
		printf("#%d  Success!\n", (int)test_id);
	} else {
		printf("Error in lookup!\n");
	}

	/*
	 * Delete the gif
	 */
	for( timeout = SEC_TIMER + 10 ; (int)(timeout - SEC_TIMER) < 0 ; ) {}

	printf("Deleting '/rabbit1.gif'... ");
tryagain_delete:
	switch(devmate_fs_delete(&file,logo_file)) {
	case TC_PENDING:
		/* finish the delete */
		while(TC_PENDING == (rv = devmate_fs_finish(&file)))
			devmate_tick();
		if(TC_SUCCESS == rv)
			break;
		/* fall through to the error state */
	case TC_ERROR:
		devmate_tick();
		goto tryagain_delete;
	case TC_SUCCESS:
		break;
	}
		
	/*********************************************************
	 * At this point the .gif file should be removed. Again, *
	 * browse to "[ip_address]/foo.html" (remember to reload *
	 * so the cache is not used!), and the picture on the    *
	 * page should be gone.                                  *
	 *********************************************************/

	printf("All done!\n");	
}