/** \file
 *
 *  Contains the FileIOStream class implementation.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 *
 */

#include "FileIOStream.h"
#include <sys/stat.h>

FileIOStream::FileIOStream( FILE* file, bool autoClose )
    : file_( file ),
      autoClose_( autoClose ),
      filename_( "unknown" )
{}

/// Constructor
FileIOStream::FileIOStream( const char* filename, bool clobber )
    : file_( NULL ),
      autoClose_( true )
{
    filename_ = filename;
    open( filename, clobber );
}

FileIOStream::~FileIOStream()
{
    if( autoClose_ )
    {
        close();
    }
}

/// reads num bytes from the stream to the buffer
IOStream& FileIOStream::read( char* buffer, size_t num )
{
    MutexLocker locker( fileMutex_ );
    if( NULL != file_ )
    {
        setBytesRead( fread( ( void * ) buffer, 1, num, file_ ) );
    }
    return *this;
}

bool FileIOStream::seek( unsigned int location )
{
    MutexLocker locker( fileMutex_ );
    if( NULL != file_ )
    {
        return fseek( file_, location, SEEK_SET ) == 0;
    }
    return false;
}

bool FileIOStream::eof()
{
    MutexLocker locker( fileMutex_ );
    if( NULL != file_ )
    {
        return feof( file_ ) != 0;
    }
    return true;
}

void FileIOStream::clearErr()
{
    MutexLocker locker( fileMutex_ );
    if( NULL != file_ )
    {
        clearerr( file_ );
    }
}

const struct stat FileIOStream::getStat()
{
    MutexLocker locker( fileMutex_ );
    struct stat statValue = {0};
    stat( filename_.cStr(), &statValue );
    return statValue;
}

/// writes num bytes from buffer to the output buffer/stream
IOStream& FileIOStream::write( const char* buffer, size_t num )
{
    MutexLocker locker( fileMutex_ );
    if( NULL != file_ )
    {
        lastWritten_ = fwrite( ( const void * ) buffer, 1, num, file_ );
    }
    return *this;
}

int FileIOStream::tell()
{
    MutexLocker locker( fileMutex_ );
    if( NULL != file_ )
    {
        return ftell( file_ );
    }
    return 0;
}

void FileIOStream::close()
{
    MutexLocker locker( fileMutex_ );
    if( NULL != file_ && stdout != file_ && stderr != file_ )
    {
        fclose( file_ );
        file_ = NULL;
    }
}

void FileIOStream::flush()
{
    MutexLocker locker( fileMutex_ );
    if( NULL != file_ )
    {
        fflush( file_ );
    }
}

bool FileIOStream::open( const char* filename, bool clobber )
{
    close();
    MutexLocker locker( fileMutex_ );
    if( clobber )
    {
        file_ = fopen( filename, "wb" );
    }
    else
    {
        file_ = fopen( filename, "r+b" );
    }
    return NULL != file_;
}
