//Copyright 2007 Asim Siddiqui
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//
//
#include <ios>
#include <stddef.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <SRF_util.hh>
#include <SRF_ReadSet.hh>
#include <SRF_Ztr.hh>

#define HEADERTYPE 'H'

SRF_ReadSet::SRF_ReadSet( void )
{
    ztrHeader.clear();
    subBlockType = 'E';
}
    

SRF_ReadSet::~SRF_ReadSet( void )
{
}

bool
SRF_ReadSet::populate( std::fstream& file )
{
    positionInFile = file.tellg();

// read dataBlockHeader fields
    char headerType = ' ';
    file.read ( &headerType, 1);
    if ( headerType != HEADERTYPE )
    {
        SRF_ReportError( "unexpected header type" );
        return FALSE;
    }

    blockSize = 0;
    file.read( reinterpret_cast<char *>(&blockSize), 4 );
    blockSize = be_int4(blockSize);

    file.read ( &subBlockType, 1);

    uniqueIdPrefix = SRF_readString( file );

    uint32_t sizeZtrHeaderBlob = blockSize - 1 - 4 - 1 - uniqueIdPrefix.size() - 1;
    if ( sizeZtrHeaderBlob < 0 )
    {
        SRF_ReportError( "invalid block size for read set" );
        return FALSE;
    }


    ztrHeader.clear();
    if ( sizeZtrHeaderBlob > 0 )
    {
	char cstr[sizeZtrHeaderBlob];
        file.read( cstr,  sizeZtrHeaderBlob);
	ztrHeader.assign(cstr,  sizeZtrHeaderBlob);
    }

   return TRUE;
}

ADOPT SRF_Read*
SRF_ReadSet::getRead( std::fstream& file )
{
    if ( file.peek() == EOF )
    {
        return NULL;
    }

    SRF_Read* read = new SRF_Read;

    if ( read->populate( ztrHeader, file ) == 0 )
    {
        delete read;
    }

    return read;
}

bool
SRF_ReadSet::readSetStart( std::fstream& file )
{
    file.seekg( positionInFile );

    return TRUE;
}

bool
SRF_ReadSet::readSetReadStart( std::fstream& file )
{
    file.seekg( (off_t) positionInFile + blockSize );

    return TRUE;
}

bool
SRF_ReadSet::setup( const std::string& uniqueIdPrefixIn, const std::string& ztrHeaderIn )
{
    uniqueIdPrefix = uniqueIdPrefixIn;
    ztrHeader = ztrHeaderIn;

    return TRUE;
}

void
SRF_ReadSet::dump( void )
{
    std::cout << "Size of read set block:" << blockSize  <<std::endl;
    std::cout << "Sub block Type" << subBlockType  <<std::endl;
    std::cout << "Unique Id Prefix:" << uniqueIdPrefix  <<std::endl;
}

bool
SRF_ReadSet::write( std::fstream& file, const std::vector<ztr_t>& ztrBlobs, const std::vector<std::string>& readIds )
{
    int sizeZtrHeaderBlob = ztrHeader.length();
    blockSize = 1 + 4 + 1 + uniqueIdPrefix.size() + 1 + sizeZtrHeaderBlob;

// write dataBlockHeader fields
    file << HEADERTYPE;
    int32_t be_blockSize = be_int4(blockSize);
    file.write(reinterpret_cast<const char*>(&be_blockSize),4);

    file << subBlockType;

    char* str = ADOPT SRF_cStrToPascalStr( uniqueIdPrefix.c_str() );
    file << str;
    delete [] str;

    file.write(ztrHeader.data(), ztrHeader.length());

    std::vector<std::string>::const_iterator stringListIterator = readIds.begin();
    std::vector<ztr_t>::const_iterator ztrVecIterator = ztrBlobs.begin();
    while( ztrVecIterator != ztrBlobs.end() )
    {
//      TODO check uniqueIdPrefix matches the start of readId

//      writeRead

        SRF_Read read( &(*stringListIterator), &(*ztrVecIterator) );
        read.write( file );


// TOOO
//      if ( indexContainer eq TRUE )
//              store readOffset from start of file
//              # will need to be stored in a tmp file
//      endif

        stringListIterator++;
        ztrVecIterator++;
    }

}
