//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 <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <SRF_Ztr.hh>
#include <SRF_util.hh>
#include <SRF_Read.hh>

#define HEADERTYPE 'R'

SRF_Read::SRF_Read( void )
{
    ztr = NULL;
    ztrConst = ztr;
}
    

SRF_Read::~SRF_Read( void )
{
    delete_ztr(ztr);
}

SRF_Read::SRF_Read( const std::string* shortIdIn, const ztr_t* ztrIn )
{
    ztr = NULL;
    shortId = *shortIdIn;
    ztrConst = ztrIn;
}

int
SRF_Read::populate( std::string& ztrHeader, std::fstream& file )
{
    positionInFile = file.tellg();

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

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

    file.read ( &readFlags, 1);

    shortId = SRF_readString( file );

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

    char* blob = new char[sizeZtrBlob];
    file.read( reinterpret_cast<char *>(blob), sizeZtrBlob );

    std::stringstream ztrStr( std::ios::out|std::ios::in|std::ios::binary );
    ztrStr.write( ztrHeader.data(), ztrHeader.length());
    ztrStr.write( blob, sizeZtrBlob );
    //std::cout.write(ztrHeader.data(), ztrHeader.length());
    //std::cout.write(blob, sizeZtrBlob);
    ztr = read_ztr( ztrStr );
    delete [] blob;

    int bytesRead = blockSize;
    return bytesRead;
}

void
SRF_Read::dump( void )
{
    
        std::cout << "ShortId:" << shortId << std::endl;
        Read* read = ztr2read( ztr );

        std::cout << read->base << std::endl;

        int ii = 0;
        while ( ii < read->NBases && read->prob_A != NULL)
        {
            std::cout << std::noshowpos << std::setw(2) << ii
		      << " A:" << std::setw(3) << std::showpos << (int) read->prob_A[ii]
		      << " C:" << std::setw(3) << std::showpos << (int) read->prob_C[ii]
		      << " G:" << std::setw(3) << std::showpos << (int) read->prob_G[ii]
		      << " T:" << std::setw(3) << std::showpos << (int) read->prob_T[ii]
		      << std::endl;
            ii++;
        }

	std::cout << "NPoints = " << std::noshowpos << read->NPoints << std::endl;
	for (ii = 0; ii < read->NPoints; ii++) {
	    std::cout << std::setw(2) << ii
		      << "   A=" << std::setw(6) << read->traceA[ii] - read->baseline
		      << "   C=" << std::setw(6) << read->traceC[ii] - read->baseline
		      << "   G=" << std::setw(6) << read->traceG[ii] - read->baseline
		      << "   T=" << std::setw(6) << read->traceT[ii] - read->baseline << std::endl;
	}

	read_deallocate(read);
}

int
SRF_Read::write( std::fstream& file )
{
    char* shortIdStr = ADOPT SRF_cStrToPascalStr( shortId.c_str() );
    uint32_t sizeZtr = SRF_calcSizeZTR( ztrConst );

//  blockType
    file << HEADERTYPE;

// block size

    blockSize = 1 + 4 + 1 + strlen( shortIdStr ) + sizeZtr;
    int32_t be_blockSize = be_int4(blockSize);
    file.write(reinterpret_cast<const char*>(&be_blockSize),4);

// readFlags
    file << readFlags;
// readId
    file << shortIdStr;
    delete [] shortIdStr;

// ztrBlob
    SRF_writeZtr( ztrConst, file );
}
