#include "OutputTrackSegmentC.h"
#include "PajaTypes.h"
#include "DataBlockI.h"
#include "EditableI.h"
#include "UndoC.h"
#include "TimeSegmentC.h"
#include "EffectI.h"
#include "GizmoI.h"
#include "ParamI.h"
#include "ImportableI.h"
#include "FileIO.h"
#include "TimeContextC.h"
#include "DeviceContextC.h"
#include "Composition.h"
#include <string>
#include <vector>
#include <stdlib.h>		//qsort


using namespace PajaTypes;
using namespace Edit;
using namespace Composition;
using namespace FileIO;
using namespace PluginClass;
using namespace Import;


enum OutputTrackSegChunksE {
	CHUNK_SEG_BASE =		0x1000,
};

const uint32	SEG_VERSION = 1;


OutputTrackSegmentC::OutputTrackSegmentC() :
	m_pParent( 0 ),
	m_i32Flags( SEGMENT_NOFLAGS ),
	m_i32StartTime( 0 ),
	m_i32EndTime( 0 ),
	m_i32OrigoTime( 0 ),
	m_pFile( 0 )
{
}

OutputTrackSegmentC::OutputTrackSegmentC( EditableI* pOriginal ) :
	EditableI( pOriginal ),
	m_pParent( 0 ),
	m_i32Flags( SEGMENT_NOFLAGS ),
	m_i32StartTime( 0 ),
	m_i32EndTime( 0 ),
	m_i32OrigoTime( 0 ),
	m_pFile( 0 )
{
}

OutputTrackSegmentC::~OutputTrackSegmentC()
{
	// if this is a clone from the original, dont delete the data.
	if( get_original() )
		return;
}

OutputTrackSegmentC*
OutputTrackSegmentC::create_new()
{
	return new OutputTrackSegmentC;
}

DataBlockI*
OutputTrackSegmentC::create()
{
	return new OutputTrackSegmentC;
}

DataBlockI*
OutputTrackSegmentC::create( EditableI* pOriginal )
{
	return new OutputTrackSegmentC( pOriginal );
}

void
OutputTrackSegmentC::copy( EditableI* pEditable )
{
	OutputTrackSegmentC*	pSeg = (OutputTrackSegmentC*)pEditable;
	m_i32Flags = pSeg->m_i32Flags;
	m_i32StartTime = pSeg->m_i32StartTime;
	m_i32EndTime  =pSeg->m_i32EndTime;
	m_pParent = pSeg->m_pParent;
	m_pFile = pSeg->m_pFile;
}

void
OutputTrackSegmentC::restore( EditableI* pEditable )
{
	OutputTrackSegmentC*	pSeg = (OutputTrackSegmentC*)pEditable;
	m_i32Flags = pSeg->m_i32Flags;
	m_i32StartTime = pSeg->m_i32StartTime;
	m_i32EndTime = pSeg->m_i32EndTime;
	m_pParent = pSeg->m_pParent;
	m_pFile = pSeg->m_pFile;
}


void
OutputTrackSegmentC::set_filehandle( FileHandleC* pHandle )
{
	m_pFile = pHandle;
}

FileHandleC*
OutputTrackSegmentC::get_filehandle()
{
	return m_pFile;
}

int32
OutputTrackSegmentC::get_start_time()
{
	return m_i32StartTime;
}

void
OutputTrackSegmentC::set_start_time( int32 i32Time )
{
	m_i32StartTime = i32Time;
}

int32
OutputTrackSegmentC::get_end_time()
{
	return m_i32EndTime;
}

void
OutputTrackSegmentC::set_end_time( int32 i32Time )
{
	m_i32EndTime = i32Time;
}

int32
OutputTrackSegmentC::get_origo_time()
{
	return m_i32OrigoTime;
}

void
OutputTrackSegmentC::set_origo_time( int32 i32Time )
{
	m_i32OrigoTime= i32Time;
}

void
OutputTrackSegmentC::set_parent( OutputTrackC* pTrack )
{
	m_pParent = pTrack;
}

OutputTrackC*
OutputTrackSegmentC::get_parent() const
{
	return m_pParent;
}


void
OutputTrackSegmentC::set_flags( int32 i32Flags )
{
	m_i32Flags = i32Flags;
}

void
OutputTrackSegmentC::add_flags( int32 i32Flags )
{
	m_i32Flags |= i32Flags;
}

void
OutputTrackSegmentC::del_flags( int32 i32Flags )
{
	m_i32Flags &= ~i32Flags;
}

void
OutputTrackSegmentC::toggle_flags( int32 i32Flags )
{
	m_i32Flags ^= i32Flags;
}

int32
OutputTrackSegmentC::get_flags()
{
	return m_i32Flags;
}



uint32
OutputTrackSegmentC::save( SaveC* pSave )
{
	uint32	ui32Error = IO_OK;
	uint32	ui32Temp;


	pSave->begin_chunk( CHUNK_SEG_BASE, SEG_VERSION );
		// flags
		ui32Error = pSave->write( &m_i32Flags, sizeof( m_i32Flags ) );
		// start time
		ui32Error = pSave->write( &m_i32OrigoTime, sizeof( m_i32OrigoTime ) );
		// start time
		ui32Error = pSave->write( &m_i32StartTime, sizeof( m_i32StartTime ) );
		// end time
		ui32Error = pSave->write( &m_i32EndTime, sizeof( m_i32EndTime ) );
		// file handle
		if( m_pFile)
			ui32Temp = m_pFile->get_id();
		else
			ui32Temp = 0xffffffff;
		ui32Error = pSave->write( &ui32Temp, sizeof( ui32Temp ) );

	pSave->end_chunk();


	return ui32Error;
}

uint32
OutputTrackSegmentC::load( LoadC* pLoad )
{
	uint32	ui32Error = IO_OK;
	uint32	ui32Temp;

	while( (ui32Error = pLoad->open_chunk()) == IO_OK ) {

		switch( pLoad->get_chunk_id() ) {
		case CHUNK_SEG_BASE:
			{
				if( pLoad->get_chunk_version() == SEG_VERSION ) {
					// flags
					ui32Error = pLoad->read( &m_i32Flags, sizeof( m_i32Flags ) );
					// origo time
					ui32Error = pLoad->read( &m_i32OrigoTime, sizeof( m_i32OrigoTime ) );
					// start time
					ui32Error = pLoad->read( &m_i32StartTime, sizeof( m_i32StartTime ) );
					// end time
					ui32Error = pLoad->read( &m_i32EndTime, sizeof( m_i32EndTime ) );
					// file handle
					ui32Error = pLoad->read( &ui32Temp, sizeof( ui32Temp ) );
					if( ui32Temp != 0xffffffff )
						pLoad->add_file_handle_patch( (void**)&m_pFile, ui32Temp );
					}
			}
			break;

		default:
			assert( 0 );
		}

		pLoad->close_chunk();

		if( ui32Error != IO_OK && ui32Error != IO_END )
			return ui32Error;
	}

	if( ui32Error != IO_OK && ui32Error != IO_END )
		return ui32Error;

	return IO_OK;
}

