/* 
 *   test_file_io.t - test of file I/O operations 
 */

#include "tads.h"
#include "t3.h"
#include "bytearr.h"
#include "file.h"
#include "bignum.h"


//------- read access level --------

test_read_no_access()
{
	local filename = 'xtads_test_readAccess.txt';

    "<br>
    --- Test: should only pass for mode \"no write access\"<br>
    --- !! requires an existing file <<filename>> in /tmp/ and game folder!!<br>
    <br>
    <br>";

	local pathAndFileName = filename;
	if (read_text_file(pathAndFileName)) 
		{
		fail_msg('could read from game dir');
		return;
		}
	
	pathAndFileName = '/tmp/' + filename;
	if (read_text_file(pathAndFileName)) 
		{
		fail_msg('could read from /tmp/');
		return;
		}

	pass_msg();	
}

test_read_game_dir_only()
{
	local filename = 'xtads_test_readAccess.txt';

    "<br>
    --- Test: should only pass for mode \"read from game folder only\"<br>
    --- !! requires an existing file <<filename>> in /tmp/ and game folder !!<br>
    <br>
    <br>";

	local pathAndFileName = filename;
	if (! read_text_file(pathAndFileName)) 
		{
		fail_msg('could not read from game dir');
		return;
		}
	
	pathAndFileName = '/tmp/' + filename;
	if (read_text_file(pathAndFileName)) 
		{
		fail_msg('could read from /tmp/');
		return;
		}

	pass_msg();	
}

test_read_anywhere()
{
	local filename = 'xtads_test_readAccess.txt';

    "<br>
    --- Test: should only pass for mode \"read from anywhere\"<br>
    --- !! requires an existing file <<filename>> in /tmp/ and game folder !!<br>
    <br>
    <br>";

	local pathAndFileName = filename;
	if (! read_text_file(pathAndFileName)) 
		{
		fail_msg('could not read from game dir');
		return;
		}
	
	pathAndFileName = '/tmp/' + filename;
	if (! read_text_file(pathAndFileName)) 
		{
		fail_msg('could not read from /tmp/');
		return;
		}

	pass_msg();	
}

//------- write access level --------

test_write_no_access()
{
    "<br>
    --- Test: should only pass for mode \"no write access\"
    <br>
    <br>";

	local pathAndFileName = 'xtads_test_writeNoAccess.txt';
	if (write_text_file(pathAndFileName, 'Line1\nLine2\n')) 
		{
		fail_msg('could write to game dir');
		return;
		}
	
	pathAndFileName = '/tmp/xtads_test_writeNoAccess.txt';
	if (write_text_file(pathAndFileName, 'Line1\nLine2\n')) 
		{
		fail_msg('could write to /tmp/');
		return;
		}
	
	pass_msg();	
}

test_write_game_dir_only()
{
    "<br>
    --- Test: should only pass for modes \"write to game folder only\" and \"write anywhere\"
    <br>
    <br>";

	local pathAndFileName = 'xtads_test_writeGameDirOnly.txt';
	if (! write_text_file(pathAndFileName, 'Line1\nLine2\n')) 
		{
		fail_msg('could not write to game dir');
		return;
		}

	pathAndFileName = '/tmp/xtads_test_writeGameDirOnly.txt';
	if (write_text_file(pathAndFileName, 'Line1\nLine2\n')) 
		{
		fail_msg('could write to /tmp/');
		return;
		}

	pass_msg();	
}

test_write_anywhere()
{
    "<br>
    --- Test: should only pass for mode \"write anywhere\"
    <br>
    <br>";
	
	local pathAndFileName = '/tmp/xtads_test_writeAnywhere.txt';
	if (! write_text_file(pathAndFileName, 'Line1\nLine2\n')) 
		{
		fail_msg('could not write to /tmp/');
		return;
		}
	
	pass_msg();	
}

//------- support --------

write_text_file(pathAndFileName, text)
{
   local fp;
   try {
   	fp = File.openTextFile(pathAndFileName, FileAccessWrite, 'us-ascii');
   } catch (FileException fExc) {
      "Error opening file <<pathAndFileName>> for writing: <<fExc.displayException()>>\n";
      return 0;
   }

   fp.writeFile(text);

   fp.closeFile();
   
   return 1;
}

read_text_file(pathAndFileName)
{
   local fp;
   try {
   	fp = File.openTextFile(pathAndFileName, FileAccessRead, 'us-ascii');
   } catch (FileException fExc) {
      "Error opening file <<pathAndFileName>> for reading: <<fExc.displayException()>>\n";
      return 0;
   }

    while (true) {
        local val = fp.readFile();
        if (val == nil) {
            break;
         }
        "read line: <<val>>\n";
    }

   fp.closeFile();
   
   return 1;
}

fail_msg(msg)
{
	"<p>
	*** Failed - <<msg>>";
}

pass_msg()
{
	"<p>
	PASS";
}

//----------------------------------------------------------------------

/*
 *   These tests are adapted from the TADS porting kit source:
 *   tads3/test/data/files.t
 */
test_files()
{
	test_text_file();
	test_text_file_readwrite_with_seeking();
	test_binary_file();
	//*TODO make work:
	test_open_file_with_weird_name();
	//*/
	test_raw_file();
   "<br>
   Done!\n";
}

test_text_file()
{
    local fp;
    local i;

    "<br>
    Text file<br>
    ----------<br>";

    /* open a file */
    try
    {
        fp = File.openTextFile('test.txt', FileAccessWrite, 'asc7dflt');
    }
    catch (FileException fExc)
    {
        "Error opening file test.txt for writing:
         <<fExc.displayException()>>\n";
        return;
    }

    /* write some data */
    for (i = 0 ; i < 100 ; ++i)
        fp.writeFile('This is line ' + i + '!!!\n');
    fp.writeFile('Some extended characters: '
                 + '\u2039 \u2122 \u00A9 \u00AE \u203A\n');

    /* close the file */
    fp.closeFile();

    /* open the file for reading */
    try
    {
        fp = File.openTextFile('test.txt', FileAccessRead, 'asc7dflt');
    }
    catch (FileException fExc)
    {
        "Error opening file test.txt for reading:
        <<fExc.displayException()>>\n";
        return;
    }

    "test.txt: size = <<fp.getFileSize()>>\n";

    /* read the data */
    for (i = 0 ; ; ++i)
    {
        local val;

        val = fp.readFile();
        if (val == nil)
            break;
        "<<i>>: <<val>>\n";
    }

    fp.closeFile();
}

test_text_file_readwrite_with_seeking()
{
    "<br>
    Text file read/write with seeking <br>
    ----------------------------------<br>";

    local fp;
    local i;

    try
    {
        fp = File.openTextFile(
            'test.txt', FileAccessReadWriteKeep, 'us-ascii');
    }
    catch (FileException fExc)
    {
        "Error opening file test.txt for read/write/keep:
        <<fExc.displayException()>>\n";
        return;
    }

    "test.txt: size = <<fp.getFileSize()>>\n";

    /* read back the data */
    local line50 = nil;
    for (i = 0 ; ; ++i)
    {
        local sol = fp.getPos();
        local val = fp.readFile();
        if (val == nil)
            break;
        else if (val.find('line 50') != nil)
            line50 = sol;
    }

    /* seek back to line 50 */
    "Seeking to <<line50>>\n";
    fp.setPos(line50);

    /* re-write the remainder of the file */
    for (i = 50 ; i < 75 ; ++i)
        fp.writeFile('This is the NEW line <<i>>!!!\n');

    /* done */
    fp.closeFile();
}

test_binary_file()
{
    "<br>
    Binary file<br>
    -----------<br>";

    local fp;
    local i;

    try
    {
        fp = File.openDataFile('test.bin', FileAccessWrite);
    }
    catch (FileException fExc)
    {
        "Error opening file test.bin for writing\n";
        return;
    }

    /* write some data */
    for (i = 0 ; i <= 100 ; i += 20)
    {
        fp.writeFile(i);
        fp.writeFile('String ' + i);
    }

    /* write a couple of BigNumber values */
    fp.writeFile(1.2345);
    fp.writeFile('BigNumber 1.2345');

    fp.writeFile(new BigNumber(12345, 10).logE());
    fp.writeFile('BigNumber ln(12345)');

    /* write a byte array */
    {
        local arr = new ByteArray(20);

        for (local i = 1 ; i <= 20 ; ++i)
            arr[i] = i*5;

        fp.writeFile(arr);
        fp.writeFile('ByteArray(20)');
    }

    /* done with the file for this round */
    fp.closeFile();

    /* open it for reading */
    try
    {
        fp = File.openDataFile('test.bin', FileAccessRead);
    }
    catch (FileException fExc)
    {
        "Error opening file test.bin for reading\n";
        return;
    }

    /* read the data back */
    for (i = 0 ; ; ++i)
    {
        local ival, sval;

        /* read the pair of values */
        if ((ival = fp.readFile()) == nil || (sval = fp.readFile()) == nil)
            break;

        /* show the first value in the pair */
        if (dataType(ival) == TypeObject && ival.ofKind(ByteArray))
        {
            "<<i>>: type ByteArray, value: [";
            for (local j = 1 ; j <= ival.length() ; ++j)
            {
                if (j > 1) ", ";
                "<<ival[j]>>";
            }
            "]";
        }
        else
        {
            "<<i>>: type <<dataType(ival)>>, value '<<ival>>'";
        }

        /* show the second of the pair (always a string) */
        "; type <<dataType(sval)>>, value '<<sval>>'\n";
    }

    /* done with the file */    
    fp.closeFile();
}

test_open_file_with_weird_name()
{
    "<br>
    Open a file with a weird name<br>
    ------------------------------<br>";

    local fp;

    local fname = 'test\u00e4\u00eb\u00ef\u00f6\u00fc\u00ff.dat';
    "Opening <<fname>> (that's 'test' + 'aeiouy' with umlauts + '.dat')\n";
    fp = File.openTextFile(fname, FileAccessWrite, 'cp437');
    fp.writeFile('Hello there!\n');
    fp.writeFile('Filename = ' + fname + '\n');
    fp.closeFile();
}

test_raw_file()
{
    "<br>
    Raw file<br>
    ---------<br>";

    local fp;

    /* open a raw file for writing */
    fp = File.openRawFile('test.raw', FileAccessWrite);

    /* write some bytes */
    local arr = new ByteArray(100);
    for (local i = 1 ; i <= arr.length() ; ++i)
        arr[i] = i;

    fp.writeBytes(arr, 11, 10);
    fp.writeBytes(arr, 1,  10);
    fp.writeBytes(arr, 21, 10);
    fp.writeBytes(arr, 31);

    /* done with the file */
    fp.closeFile();
}

