/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/



#include <string.h>
#include "heap.hxx"


#include <iostream>
#include <stdlib.h>
#define AssertionOf(x)	{if (!(x)) {std::cerr << "Assertion failed: " << #x << __FILE__ << __LINE__ << std::endl; exit(3); }}

#ifdef UNX
#define stricmp strcasecmp
#endif



Heap::Heap(unsigned	i_nWidth)
	:	dpColumnsArray(new Column[i_nWidth]),
		nColumnsArraySize(i_nWidth),
		nActiveColumn(nColumnsArraySize-1)
{
	for ( unsigned i = 0; i < nColumnsArraySize; i++)
	{
		dpColumnsArray[i] = 0;
	}  // end for
}

Heap::~Heap()
{
	for ( unsigned i = 0; i < nColumnsArraySize; i++)
	{
		HeapItem * & rColumn = dpColumnsArray[i];
		for ( HeapItem * pValue = rColumn; pValue != 0; pValue = rColumn )
		{
			rColumn = rColumn->Next();
			delete pValue;
		}
	}  // end for

	delete [] dpColumnsArray;
}

void
Heap::InsertValue( const char *		i_sKey,
				   const char *	   	i_sValue )
{
	HeapItem * pSearch1 = 0;
	HeapItem * pSearch2 = 0;
	HeapItem * pNew = new HeapItem(i_sKey, i_sValue);

	IncColumn();
	pSearch1 = ActiveColumn();

	if ( pSearch1 != 0 ? *pNew < *pSearch1 : true )
	{
		pNew->SetNext( pSearch1 );
		ActiveColumn() = pNew;

		if ( pNew->Next() != 0)
		{
			AssertionOf( *pNew <= *pNew->Next() );
		}

		return;
	}

	do
	{
		pSearch2 = pSearch1;
		pSearch1 = pSearch1->Next();

		if ( pSearch1 != 0 ? *pNew < *pSearch1 : true )
		{
			pNew->SetNext( pSearch1 );
			pSearch2->SetNext(pNew);


		AssertionOf( *pSearch2 <= *pNew );
		if ( pNew->Next() != 0)
		{
			AssertionOf( *pNew <= *pNew->Next() );
		}

		}
	} while (pSearch2->Next() != pNew);
}


Simstr sKey1;
Simstr sValue1;
Simstr sKey2;
Simstr sValue2;
int nCol1 = 0;
int nCol2 = 0;


HeapItem *
Heap::ReleaseTop()
{
	unsigned nRetColumn = 0;
	HeapItem * ret = dpColumnsArray[0];
	HeapItem * pSearch = 0;

	for ( unsigned i = 1; i < nColumnsArraySize; ++i )
	{
		pSearch = dpColumnsArray[i];
		if (pSearch != 0)
		{
			if ( ret == 0 ? true : *pSearch < *ret)
			{
				ret = pSearch;
				nRetColumn = i;
			}
		}
	}	// for

	if (ret != 0)
	{
		dpColumnsArray[nRetColumn] = ret->Next();
	}
	return ret;
}

void
Heap::IncColumn()
{
	if (++nActiveColumn >= nColumnsArraySize)
		nActiveColumn = 0;
}



HeapItem::HeapItem( const char *		i_sKey,
					const char *	   	i_sValue )
	:	sValue(i_sValue),
		sKey(i_sKey),
		pNext(0)
{
}

HeapItem::~HeapItem()
{
}

bool
HeapItem::operator<( const HeapItem & i_rOther ) const
{
	int ret = stricmp(sKey.str(), i_rOther.sKey.str());
	if (ret == 0)
		ret = strcmp(sKey.str(), i_rOther.sKey.str());
	if (ret == 0)
		ret = stricmp(sValue.str(), i_rOther.sValue.str());
	if (ret == 0)
		ret = strcmp(sValue.str(), i_rOther.sValue.str());
	return ret < 0;
}

const Simstr &
HeapItem::Value() const
{
	return sValue;
}

const Simstr &
HeapItem::Key() const
{
	return sKey;
}

HeapItem *
HeapItem::Next() const
{
	return pNext;
}

void
HeapItem::SetNext( HeapItem * i_pNext )
{
	pNext = i_pNext;
}


