#include "Cache.h"
#include "FileIterator.h"

#include <iostream>

using namespace std;

FileIterator::FileIterator(ASFFileInputStream* parent, int id)
    : m_lPos(0), m_pParent(parent), m_iId(id),
    m_SeekInfo(m_pParent->m_SeekInfo[id])
{
}

FileIterator::~FileIterator()
{
}

packet FileIterator::getPacket(bool& success)
{
    const MainASFHeader& header = m_pParent->m_Header;
    pthread_mutex_t& mutex = m_pParent->m_Mutex;
    int& fd = m_pParent->m_iFd;

    //cout << "Pos packer " << m_iId << "  " << m_lPos << "    num " << header.num_packets << "   si " << m_SeekInfo->size() << endl;
    if (m_lPos < 0 || m_lPos >= (int)header.num_packets)
    {
        success=false;
	return packet();
    }
    packet p(header.pktsize);
    pthread_mutex_lock(&mutex);
    //cout << "seek " << m_pParent->m_lDataOffset + m_lPos * header.pktsize << "  sz: " << header.pktsize << endl;
    lseek64(fd, m_pParent->m_lDataOffset + m_lPos * header.pktsize, SEEK_SET);
    if (read(fd, &p[0], header.pktsize) <= 0)
    {
        // FIXME - missing check for unix signal and restart - maybe add later
	cout << "asfinput:: read fail " << header.pktsize << endl;
	success=false;
	pthread_mutex_unlock(&mutex);
	return packet();
    };
    pthread_mutex_unlock(&mutex);
    p.init();
    if (p.hdr.length!=0xFF)
	success=true;
    else
	success=false;
    return p;
}

HRESULT FileIterator::seek(double timestamp, chunk_info* pch)
{
    int info_pos = m_SeekInfo->find(int(timestamp*1000.));
    if (info_pos < 0)
	return -1;
    const chunk_info& ch = (*m_SeekInfo)[info_pos];
    m_lPos = ch.packet_id;
    *pch = ch;
//    _iterator->Seek(ch.packet_id);
//    _chunk=ch.packet_id;
//    _position=ch.fragment_id;
//    _pointer=0;
//    _last_timestamp=ch.object_start_time/1000.;
    return 0;
}

HRESULT FileIterator::seek(int64_t lPos, chunk_info* pch)
{
    if (lPos < 0 || lPos >= m_SeekInfo->size())
	return -1;

    int info_pos = lPos;
    const chunk_info& ch = (*m_SeekInfo)[info_pos];
    m_lPos = ch.packet_id;
    *pch = ch;
    return 0;
}

//FileIterator _this_is_completely_unused_file_iterator(0,0);
void FileIterator::undo()
{
    if (m_Undo.size() > 0)
    {
	m_lPos = m_Undo.back();
	m_Undo.pop_back();
    }
}

void FileIterator::undoPosition()
{
    m_Undo.push_back(m_lPos);
}

void FileIterator::forgetUndo()
{
    if (m_Undo.size() > 0)
	m_Undo.pop_back();
}
