#ifndef __STATEFILE_BYTELISTTEST_H
#define __STATEFILE_BYTELISTTEST_H

#include <cxxtest/TestSuite.h>
#include <string>
#include <memory.h>
#include "stdlib.h"
#include "ByteData.hxx"

class ByteDataTest : public CxxTest::TestSuite {
    StateFile::ByteData empty;
    StateFile::ByteData notEmpty8;
    StateFile::ByteData notEmpty32;
    std::fstream fi;
      
    uint8 a8;
    uint32 a32, b32;


public:
    ByteDataTest()  {}
    virtual ~ByteDataTest() { }
    
    static ByteDataTest *createSuite() { return new ByteDataTest(); }
    static void destroySuite( ByteDataTest *suite ) { delete suite; }

    void setUp() {
      a8 = 8;
      a32 = 8;
      b32 = 8 + 256*256;

      notEmpty8  = StateFile::ByteData8();
      notEmpty32 = StateFile::ByteData32();
    }

    void test_UintConversions() {
      
      TS_ASSERT_EQUALS( a8, a32 );
      TS_ASSERT_EQUALS( a8, (uint8)a32 );
      TS_ASSERT_EQUALS( a8, (uint8)b32 );
      TS_ASSERT_DIFFERS( a8, b32 );
      TS_ASSERT_DIFFERS( (uint32)a8, b32 );
    }

    void test_SetStrings() {
      std::string *hi = new std::string("hi");
      TS_ASSERT_EQUALS( 2, hi->length() );
    
      notEmpty8.setData( (uint8*)(hi->c_str()), hi->length() );

      std::string *result = notEmpty8.toString();

      TS_ASSERT_EQUALS( hi->compare( result->c_str() ), 0 );

      delete hi;
      delete result;

      std::string *bye = new std::string( "bye" );
      
      notEmpty32.setData( bye );
      
      result = notEmpty32.toString();

      TS_ASSERT_EQUALS( bye->compare( result->c_str() ), 0 );

      delete bye;
      delete result;
      
      notEmpty32.clear();
      
      TS_ASSERT( ! notEmpty32.getData() );
      TS_ASSERT_EQUALS( notEmpty32.getSize(), 0 );   
    }

};

class fileByteDataTest : public CxxTest::TestSuite {
    StateFile::ByteData empty;
    StateFile::ByteData notEmpty8;
    StateFile::ByteData notEmpty32;
    std::fstream fi;
      
    char *testFileName;
    char *removeTestFile;
    std::string *hi, *byte, *skip;

 public:
    fileByteDataTest()  {}
    virtual ~fileByteDataTest() { }

    static fileByteDataTest *createSuite() { return new fileByteDataTest(); }
    static void destroySuite( fileByteDataTest *suite ) { delete suite; }

    void setUp() {

      notEmpty8  = StateFile::ByteData8();
      notEmpty32 = StateFile::ByteData32();
      empty      = StateFile::ByteData32();

      testFileName = ".blt.test";
      removeTestFile = "/bin/rm .blt.test";

      hi = new std::string("hi");
      byte = new std::string("byte");
      skip = new std::string("skip");

      // Write a file (in binary):
      //  2:8,"hi",4:32,"skip",4:32,"byte"
      fi.open( testFileName, std::ios::out | std::ios::binary );  
      TS_ASSERT( fi );

      notEmpty8.setData( hi );
      TS_ASSERT( notEmpty8.fileWrite( &fi ) );

      notEmpty32.setData( skip );
      TS_ASSERT( notEmpty32.fileWrite( &fi ) );
      notEmpty32.clear();

      notEmpty32.setData( (uint8*)(byte->c_str()), byte->length() );
      TS_ASSERT( notEmpty32.fileWrite( &fi ) );

      TS_ASSERT( notEmpty32.fileWrite( &fi, true ) ); // skip
      fi.close();

      notEmpty8.clear();
      notEmpty32.clear();
    }

    void tearDown() {
      delete hi;
      delete byte;
      delete skip;
      system( removeTestFile );
    }

    void test_StringFileIO() {
      std::string *result;

      TS_ASSERT_EQUALS( notEmpty8.getSize(), 0 );
      TS_ASSERT_EQUALS( empty.getSize(), 0 );
      TS_ASSERT_EQUALS( notEmpty32.getSize(), 0 );

      TS_ASSERT( ! notEmpty8.getData() );
      TS_ASSERT( ! empty.getData() );
      TS_ASSERT( ! notEmpty32.getData() );

      fi.open( testFileName, std::ios::in | std::ios::binary );
      TS_ASSERT( fi );
      // notEmpty8
      TS_ASSERT( notEmpty8.fileRead( &fi ) );
      TS_ASSERT_LESS_THAN( 0, notEmpty8.getSize() );
      TS_ASSERT_EQUALS( notEmpty8.getSize(), 2 );
      TS_ASSERT( result = notEmpty8.toString() );
      TS_ASSERT_EQUALS( strncmp( result->c_str(), hi->c_str(), 2 ),0 );
      delete result;

      // empty
      TS_ASSERT( empty.fileRead( &fi, true ) );
      TS_ASSERT_EQUALS( empty.getSize(), 0 );
      TS_ASSERT( ! empty.getData() );
      
      // notEmpty32
      TS_ASSERT( notEmpty32.fileRead( &fi ) );
      TS_ASSERT_LESS_THAN( 0, notEmpty32.getSize() );
      TS_ASSERT_EQUALS( notEmpty32.getSize(), 4 );
      TS_ASSERT( result = notEmpty32.toString() );
      TS_ASSERT_EQUALS( byte->compare( result->c_str() ), 0 );
      delete result;

      // empty (skipped write)
      TS_ASSERT( empty.fileRead( &fi ) );
      TS_ASSERT_EQUALS( empty.getSize(), 0 );
      TS_ASSERT( ! empty.getData() );

      fi.close();
    }

};


#endif // __STATEFILE_BYTELISTTEST_H

