/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmlhelp.hxx"

#include "db.hxx"

#include <rtl/alloc.h>
#include <cstring>

#include "com/sun/star/io/XSeekable.hpp"

using namespace com::sun::star::uno;
using namespace com::sun::star::io;

namespace helpdatafileproxy {

//----------------------------------------------------------------------------
void HDFData::copyToBuffer( const char* pSrcData, int nSize )
{
	m_nSize = nSize;
	delete [] m_pBuffer;
	m_pBuffer = new char[m_nSize+1];
	memcpy( m_pBuffer, pSrcData, m_nSize );
	m_pBuffer[m_nSize] = 0;
}


// Hdf

bool Hdf::implReadLenAndData( const char* pData, int& riPos, HDFData& rValue )
{
	bool bSuccess = false;

	// Read key len
	const char* pStartPtr = pData + riPos;
	char* pEndPtr;
	sal_Int32 nKeyLen = strtol( pStartPtr, &pEndPtr, 16 );
	if( pEndPtr == pStartPtr )
		return bSuccess;
	riPos += (pEndPtr - pStartPtr) + 1;

	const char* pKeySrc = pData + riPos;
	rValue.copyToBuffer( pKeySrc, nKeyLen );
	riPos += nKeyLen + 1;

	bSuccess = true;
	return bSuccess;
}

void Hdf::createHashMap( bool bOptimizeForPerformance )
{
	releaseHashMap();
	if( bOptimizeForPerformance )
	{
		if( m_pStringToDataMap != NULL )
			return;
		m_pStringToDataMap = new StringToDataMap();
	}
	else
	{
		if( m_pStringToValPosMap != NULL )
			return;
		m_pStringToValPosMap = new StringToValPosMap();
	}

	Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileURL );
	if( xIn.is() )
	{
		Sequence< sal_Int8 > aData;
		sal_Int32 nSize = m_xSFA->getSize( m_aFileURL );
		sal_Int32 nRead = xIn->readBytes( aData, nSize );

		const char* pData = (const char*)aData.getConstArray();
		int iPos = 0;
		while( iPos < nRead )
		{
			HDFData aDBKey;
			if( !implReadLenAndData( pData, iPos, aDBKey ) )
				break;

			rtl::OString aOKeyStr = aDBKey.getData();

			// Read val len
			const char* pStartPtr = pData + iPos;
			char* pEndPtr;
			sal_Int32 nValLen = strtol( pStartPtr, &pEndPtr, 16 );
			if( pEndPtr == pStartPtr )
				break;

			iPos += (pEndPtr - pStartPtr) + 1;

			if( bOptimizeForPerformance )
			{
				const char* pValSrc = pData + iPos;
				rtl::OString aValStr( pValSrc, nValLen );
				(*m_pStringToDataMap)[aOKeyStr] = aValStr;
			}
			else
			{
				// store value start position
				(*m_pStringToValPosMap)[aOKeyStr] = std::pair<int,int>( iPos, nValLen );
			}
			iPos += nValLen + 1;
		}

		xIn->closeInput();
	}
}

void Hdf::releaseHashMap( void )
{
	if( m_pStringToDataMap != NULL )
	{
		delete m_pStringToDataMap;
		m_pStringToDataMap = NULL;
	}
	if( m_pStringToValPosMap != NULL )
	{
		delete m_pStringToValPosMap;
		m_pStringToValPosMap = NULL;
	}
}


bool Hdf::getValueForKey( const rtl::OString& rKey, HDFData& rValue )
{
	bool bSuccess = false;
	if( !m_xSFA.is() )
		return bSuccess;

	try
	{

	if( m_pStringToDataMap == NULL && m_pStringToValPosMap == NULL )
	{
		bool bOptimizeForPerformance = false;
		createHashMap( bOptimizeForPerformance );
	}

	if( m_pStringToValPosMap != NULL )
	{
		StringToValPosMap::const_iterator it = m_pStringToValPosMap->find( rKey );
		if( it != m_pStringToValPosMap->end() )
		{
			const std::pair<int,int>& rValPair = it->second;
			int iValuePos = rValPair.first;
			int nValueLen = rValPair.second;

			Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileURL );
			if( xIn.is() )
			{
				Reference< XSeekable > xXSeekable( xIn, UNO_QUERY );
				if( xXSeekable.is() )
				{
					xXSeekable->seek( iValuePos );

					Sequence< sal_Int8 > aData;
					sal_Int32 nRead = xIn->readBytes( aData, nValueLen );
					if( nRead == nValueLen )
					{
						const char* pData = (const sal_Char*)aData.getConstArray();
						rValue.copyToBuffer( pData, nValueLen );
						bSuccess = true;
					}
				}
				xIn->closeInput();
			}
		}
	}

	else if( m_pStringToDataMap != NULL )
	{
		StringToDataMap::const_iterator it = m_pStringToDataMap->find( rKey );
		if( it != m_pStringToDataMap->end() )
		{
			const rtl::OString& rValueStr = it->second;
			int nValueLen = rValueStr.getLength();
			const char* pData = rValueStr.getStr();
			rValue.copyToBuffer( pData, nValueLen );
			bSuccess = true;
		}
	}

	}
	catch( Exception & )
	{
		bSuccess = false;
	}

	return bSuccess;
}

bool Hdf::startIteration( void )
{
	bool bSuccess = false;

	sal_Int32 nSize = m_xSFA->getSize( m_aFileURL );

	Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileURL );
	if( xIn.is() )
	{
		m_nItRead = xIn->readBytes( m_aItData, nSize );
		if( m_nItRead == nSize )
		{
			bSuccess = true;
			m_pItData = (const char*)m_aItData.getConstArray();
			m_iItPos = 0;
		}
		else
		{
			stopIteration();
		}
	}

	return bSuccess;
}

bool Hdf::getNextKeyAndValue( HDFData& rKey, HDFData& rValue )
{
	bool bSuccess = false;

	if( m_iItPos < m_nItRead )
	{
		if( implReadLenAndData( m_pItData, m_iItPos, rKey ) )
		{
			if( implReadLenAndData( m_pItData, m_iItPos, rValue ) )
				bSuccess = true;
		}
	}

	return bSuccess;
}

void Hdf::stopIteration( void )
{
	m_aItData = Sequence<sal_Int8>();
	m_pItData = NULL;
	m_nItRead = -1;
	m_iItPos = -1;
}
} // end of namespace helpdatafileproxy
