#include "dataqueue.h"

void CDataQueue::Insert( CDataRange range )
{
	if (range.Start() == range.End())
		return;

	MyList::iterator iter = m_ranges.begin();
	while (iter != m_ranges.end() && iter->End() < range.Start())
		++iter;

	if (iter == m_ranges.end())
	{
		m_ranges.push_back( range );
		return;
	}

//	std::cout << "DATARANGE: insert " << range.Start() << " " << range.End() << std::endl;
//	Dump("into");

	while (true)
	{
		MyList::iterator next = iter; ++next;
		if (next != m_ranges.end() && range.End() >= next->Start())
		{
			range = CDataRange(range.Start(), max(next->End(), range.End()) );
			m_ranges.erase( next );
			continue;
		}
		break;
	}
	if (Mergable(*iter, range))
	{
		*iter = CDataRange(min(iter->Start(), range.Start()), max(iter->End(), range.End()));
	}
	else
	{
		m_ranges.insert( iter, range );
	}

//	Dump("gets");
}

bool CDataQueue::Remove( unsigned index )
{
	MyList::iterator iter;
	for (iter = m_ranges.begin(); iter != m_ranges.end(); ++iter)
		if (iter->End() > index)
			break;
	if (iter == m_ranges.end())
		return false;
	if (iter->Start() > index)
		return false;
	if (iter->End() == index+1)
	{
		if (index == iter->Start())
			m_ranges.erase( iter );
		else
			*iter = CDataRange(iter->Start(), index);
	}
	else if (iter->Start() == index)
	{
		*iter = CDataRange(iter->Start()+1, iter->End());
	}
	else
	{
		unsigned oldEnd = iter->End();
		*iter = CDataRange(iter->Start(), index);
		++iter;
		m_ranges.insert( iter, CDataRange(index+1, oldEnd) );
	}
	return true;
}

unsigned CDataQueue::Count() const
{
	unsigned count = 0;
	for (MyList::const_iterator iter = m_ranges.begin(); iter != m_ranges.end(); ++iter)
		count += iter->End() - iter->Start();
	return count;
}

void CDataQueue::Dump( const char * hdr /* = NULL */, std::ostream& out /* = std::cout  */ ) const
{
	if (hdr)
		out << "DATAQUEUE: " << hdr << std::endl;
	for (MyList::const_iterator iter = m_ranges.begin(); iter != m_ranges.end(); ++iter)
	{
		out << "  " << iter->Start() << " " << iter->End() << std::endl;
	}
}

bool CDataQueue::HasIslands( unsigned lastPacket )
{
	if (m_ranges.empty())
		return false;
	if (m_ranges.back().End() != lastPacket)
		return true;
	if (m_ranges.size() > 1)
		return true;
	return false;
}

void CDataQueue::Merge( const CDataQueue& other )
{
	for (MyList::const_iterator iter = other.m_ranges.begin(); iter != other.m_ranges.end(); ++iter)
		Insert( *iter );
}
