/* This file is (c) 2017 Abs62
 * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */

#include "splitfile.hh"
#include "fsencoding.hh"

namespace SplitFile
{

SplitFile::SplitFile() :
  currentFile( 0 )
{
}

SplitFile::~SplitFile()
{
  close();
}

void SplitFile::appendFile( const QString & name )
{
  if( offsets.isEmpty() )
    offsets.append( 0 );
  else
    offsets.append( offsets.last() + files.last()->size() );
  files.append( new QFile( name ) );
}

void SplitFile::close()
{
  for( QVector< QFile * >::const_iterator i = files.begin(); i != files.end(); ++i )
  {
    (*i)->close();
    delete (*i);
  }

  files.clear();
  offsets.clear();

  currentFile = 0;
}

void SplitFile::getFilenames( vector< string > &names ) const
{
  for( QVector< QFile const * >::const_iterator i = files.begin(); i != files.end(); ++i )
    names.push_back( FsEncoding::encode( (*i)->fileName() ) );
}

bool SplitFile::open( QFile::OpenMode mode )
{
  for( QVector< QFile * >::iterator i = files.begin(); i != files.end(); ++i )
    if( !(*i)->open( mode ) )
    {
      close();
      return false;
    }

  return true;
}

bool SplitFile::seek( quint64 pos )
{
  if( offsets.isEmpty() )
    return false;

  int fileNom;

  for( fileNom = 0; fileNom < offsets.size() - 1; fileNom++ )
    if( pos < offsets.at( fileNom + 1 ) )
      break;

  pos -= offsets.at( fileNom );

  currentFile = fileNom;
  return files.at( fileNom )->seek( pos );
}

qint64 SplitFile::read( char *data, qint64 maxSize )
{
  if( offsets.isEmpty() )
    return 0;

  quint64 bytesReaded = 0;
  for( int i = currentFile; i < files.size(); i++ )
  {
    if( i != currentFile )
    {
      files.at( i )->seek( 0 );
      currentFile = i;
    }

    qint64 ret = files.at( i )->read( data + bytesReaded, maxSize );
    if( ret < 0 )
      break;

    bytesReaded += ret;
    maxSize -= ret;

    if( maxSize <= 0 )
      break;
  }
  return bytesReaded;
}

QByteArray SplitFile::read( qint64 maxSize )
{
  QByteArray data;
  data.resize( maxSize );

  qint64 ret = read( data.data(), maxSize );

  if( ret != maxSize )
    data.resize( ret );

  return data;
}

bool SplitFile::getChar( char *c )
{
  char ch;
  return read( c ? c : &ch, 1 ) == 1;
}

qint64 SplitFile::pos() const
{
  if( offsets.isEmpty() )
    return 0;

  return offsets.at( currentFile ) + files.at( currentFile )->pos();
}

} // namespace SplitFile
