#include "NetworkIterator.h"
#include "AsfNetworkInputStream.h"
#include <utils.h>
#include <iostream>
using namespace std;

NetworkIterator::NetworkIterator(ASFNetworkInputStream* parent)
    :m_bValid(false)
{
    m_pParent = parent;
    m_It = m_pParent->m_Cache.end();
}

NetworkIterator::~NetworkIterator()
{
}

HRESULT NetworkIterator::seek(double timestamp, chunk_info* pch)
{
    if (m_pParent->m_Ctype==Live)
	return -1;
    m_bValid=true;
    m_pParent->seekInternal(int(timestamp*1000), this);
    pch->keyframe=1;
    pch->fragment_id=0;
    pch->object_start_time=int(m_pParent->m_iTime*1000.);

    return 0;
}

HRESULT NetworkIterator::seek(int64_t timestamp, chunk_info* pch)
{
    cout<<"WARNING : NetworkIterator::seek(int64_t) is unsupported"<<endl;
    return -1;
}

packet NetworkIterator::getPacket(bool& success)
{
    Debug cout<<"NetworkIterator::getPacket()"<<endl;
    m_bValid=true;
    if(!m_pParent)
    {
	cout<<"WARNING: requested packet from illegal network iterator"<<endl;
	success=false;
	return packet();
    }
    pthread_mutex_t* mutex=&m_pParent->m_Mutex;
//    pthread_mutex_t& condm_Mutex=m_pParent->_condm_Mutex;
    pthread_cond_t* cond=&m_pParent->m_Cond;
//    bool& interrupt=m_pParent->_interrupt;
    pthread_mutex_lock(mutex);
    if(!m_pParent->m_bHeadersValid)//shouldn't happen
	pthread_cond_wait(cond, mutex);
    if(!m_pParent->m_bHeadersValid)
    {
        pthread_mutex_unlock(mutex);
	cout<<"WARNING: Invalid headers\n";
        success=false;
        return packet();
    }
//    pthread_mutex_unlock(mutex);

//    while(1)
//    {
//	pthread_mutex_lock(mutex);
//    if(!m_bValid)
//    {
//        cout<<"WARNING: access to invalid network iterator"<<endl;
//        pthread_mutex_unlock(mutex);
//	success=false;
//    	return packet();
//    }

    if(m_It==m_pParent->m_Cache.end())
    {
	pthread_cond_wait(cond, mutex);
	//cout << "Now CondWait DONE" << endl;
    }

    if(m_It==m_pParent->m_Cache.end())
    {
        cout<<"WARNING: NetworkIterator::GetPacket() interrupted"<<endl;
        pthread_mutex_unlock(mutex);
        success=false;
        return packet();
    }

//    cout<<"Valid packet "<<*_it<<endl;
    packet* p=*m_It;
//	    cout<<"Packet size:"<<flush;
//	    cout<<p->size()<<endl;
    if(!p->size())
    {
	cout<<"WARNING: bad packet size\n";
	cout<<"Cache size: "<<m_pParent->m_Cache.size()<<endl;
	cout<<"Dumping cache:\n";
	std::list<packet*>::iterator it=m_pParent->m_Cache.begin();
	int cnt=0;
	for(;it!=m_pParent->m_Cache.end(); it++)
	{
	    cout<<cnt<<": "<<"size "<<(*it)->size()<<", length "<<(*it)->hdr.packet_length<<", send time "<<(*it)->hdr.send_time<<" ms\n";
	    cnt++;
	}

	pthread_mutex_unlock(mutex);
	avi_usleep(100000);
        success=false;
        return packet();
    }
    packet answer=*p;
    pthread_mutex_unlock(mutex);
//	    cout<<"Calling init()"<<endl;
    answer.init();
    Debug cout<<"Returning: length "<<answer.hdr.packet_length<<", send time "<<answer.hdr.send_time<<" ms\n";
    if(answer.hdr.length!=0xFF)
        success=true;
    else
        success=false;
    return answer;
}

void NetworkIterator::releaseInternal()
{
    m_iRefcount--; m_pParent=0; if(!m_iRefcount)delete this;
}

void NetworkIterator::release()
{
    m_iRefcount--;
    if(!m_iRefcount)
    {
	if(m_pParent)m_pParent->unregister(this);
	delete this;
    }
}

void NetworkIterator::forgetUndo()
{
    m_UndoIt.pop_back();
    m_pParent->recheck();
}
