
#include "PajaTypes.h"
#include "DataBlockI.h"
#include "EditableI.h"
#include "LayerC.h"
#include "EffectI.h"
#include "GizmoI.h"
#include "UndoC.h"
#include <vector>
#include "ImportableI.h"
#include "FileListC.h"
#include "FileIO.h"
#include "FileHandleC.h"
#include "DeviceFeedbackC.h"

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


FileListC::FileListC()
{
	// empty
}

FileListC::FileListC( EditableI* pOriginal ) :
	EditableI( pOriginal )
{
	// empty
}

FileListC::~FileListC()
{
	// if this is clone dont delete the importables.
	if( get_original() )
		return;

	// remove file handles
	for( uint32 i = 0; i < m_rFiles.size(); i++ ) {
		if( m_rFiles[i]->get_importable() )
			m_rFiles[i]->get_importable()->release();
		m_rFiles[i]->release();
	}
}

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

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

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

void
FileListC::copy( EditableI* pEditable )
{
	FileListC*	pList = (FileListC*)pEditable;
	m_rFiles = pList->m_rFiles;
}

void
FileListC::restore( EditableI* pEditable )
{
	FileListC*	pList = (FileListC*)pEditable;
	m_rFiles = pList->m_rFiles;
}

PluginClass::SuperClassIdC
FileListC::get_base_class_id() const
{
	return BASECLASS_FILELIST;
}

FileHandleC*
FileListC::add_file( ImportableI* pImportable, FileHandleC* pFolder )
{
	FileHandleC*	pHandle = FileHandleC::create_new();

	pHandle->set_importable( pImportable );
	pHandle->set_parent_handle( pFolder );

	pImportable->set_parent( pHandle );

	m_rFiles.push_back( pHandle );

	if( get_undo() ) {
		get_undo()->add_discardable_data( pImportable, DATA_CREATED );
		get_undo()->add_discardable_data( pHandle, DATA_CREATED );
	}

	return pHandle;
}

FileHandleC*
FileListC::add_folder( const char* szName, FileHandleC* pFolder )
{
	FileHandleC*	pHandle = FileHandleC::create_new();

	pHandle->set_folder_name( szName );
	pHandle->set_flags( FILEHANDLE_FOLDER );
	pHandle->set_importable( 0 );
	pHandle->set_parent_handle( pFolder );

	m_rFiles.push_back( pHandle );

	if( get_undo() ) {
		get_undo()->add_discardable_data( pHandle, DATA_CREATED );
	}

	return pHandle;
}

uint32
FileListC::get_file_count()
{
	return m_rFiles.size();
}

void
FileListC::reload_file( uint32 ui32Index, DemoInterfaceC* pIface )
{
	if( ui32Index < m_rFiles.size() && get_undo() ) {

		ImportableI* pImportable;
		ImportableI* pOldImportable = m_rFiles[ui32Index]->get_importable();

		// createa a new instance of same kind of importable
		pImportable = (ImportableI*)pOldImportable->create();

		if( !pImportable )
			return;

		// copy settings
		pImportable->copy( pOldImportable );

		// load the new file
		pImportable->load_file( pOldImportable->get_filename(), pIface );
		pIface->initialize_importable( pImportable, INIT_INITIAL_UPDATE );

		// put the old importable to the undo stack
		get_undo()->add_discardable_data( m_rFiles[ui32Index]->get_importable(), DATA_REMOVED );
		get_undo()->add_discardable_data( pImportable, DATA_CREATED );

		// replace the old importable with new one
		UndoC*	pOldUndo = m_rFiles[ui32Index]->begin_editing( get_undo() );
		m_rFiles[ui32Index]->set_importable( pImportable );
		m_rFiles[ui32Index]->end_editing( pOldUndo );
	}
}

void
FileListC::replace_file( uint32 ui32Index, const char* szName, DemoInterfaceC* pIface )
{
	if( ui32Index < m_rFiles.size() && get_undo() ) {

		ImportableI* pImportable;
		ImportableI* pOldImportable = m_rFiles[ui32Index]->get_importable();

		// createa a new instance of same kind of importable
		pImportable = (ImportableI*)pOldImportable->create();

		if( !pImportable )
			return;

		// load the new file
		pImportable->load_file( szName, pIface );
		pIface->initialize_importable( pImportable, INIT_INITIAL_UPDATE );

		// put the old importable to the undo stack
		get_undo()->add_discardable_data( m_rFiles[ui32Index]->get_importable(), DATA_REMOVED );
		get_undo()->add_discardable_data( pImportable, DATA_CREATED );

		// replace the old importable with new one
		UndoC*	pOldUndo = m_rFiles[ui32Index]->begin_editing( get_undo() );
		m_rFiles[ui32Index]->set_importable( pImportable );
		m_rFiles[ui32Index]->end_editing( pOldUndo );
	}
}

bool
FileListC::prompt_properties( uint32 ui32Index )
{
	bool	bRes = true;
	if( ui32Index < m_rFiles.size() && get_undo() ) {
		ImportableI* pImportable = m_rFiles[ui32Index]->get_importable();
		if( !pImportable )
			return false;
		UndoC*	pOldUndo = pImportable->begin_editing( get_undo() );
		bRes = pImportable->prompt_properties();
		pImportable->end_editing( pOldUndo );
	}

	return bRes;
}


FileHandleC*
FileListC::get_file( uint32 ui32Index )
{
	if( ui32Index < m_rFiles.size() )
		return m_rFiles[ui32Index];
	return 0;
}


FileHandleC*
FileListC::get_file( const char* szName, const SuperClassIdC& rSuperFilter, const ClassIdC& rClassFilter )
{
	char szFname[_MAX_FNAME];
	char szExt[_MAX_EXT];
	_splitpath( szName, 0, 0, szFname, szExt );
	strcat( szFname, szExt );

	int32	i32Size = strlen( szFname );
	if( i32Size < 1 )
		return 0;

	char	szCurFname[_MAX_FNAME];
	char	szCurExt[_MAX_EXT];
	int32	i32CurSize;

	for( uint32 i = 0; i < m_rFiles.size(); i++ ) {
		ImportableI* pImportable = m_rFiles[i]->get_importable();
		if( !pImportable )
			continue;
		_splitpath( pImportable->get_filename(), 0, 0, szCurFname, szCurExt );
		strcat( szCurFname, szCurExt );
		i32CurSize = strlen( szCurFname );
		if( i32CurSize < i32Size )
			i32CurSize = i32Size;

		if( _strnicmp( szCurFname, szFname, i32CurSize ) == 0 ) {

			if( pImportable->get_super_class_id() == rSuperFilter && (rClassFilter == NULL_CLASSID || rClassFilter == pImportable->get_class_id()) ) {
				// found match
				return m_rFiles[i];
			}
		}

	}

	return 0;
}


FileHandleC*
FileListC::get_equal_file( ImportableI* pImportable )
{
	for( uint32 i = 0; i < m_rFiles.size(); i++ ) {
		ImportableI* pImp = m_rFiles[i]->get_importable();
		if( pImp && pImp->equals( pImportable ) )
			return m_rFiles[i];
	}
	return 0;
}

void
FileListC::del_file( uint32 ui32Index )
{
	if( ui32Index < m_rFiles.size() ) {
		if( get_undo() ) {
			if( m_rFiles[ui32Index]->get_importable() )
				get_undo()->add_discardable_data( m_rFiles[ui32Index]->get_importable(), DATA_REMOVED );
			get_undo()->add_discardable_data( m_rFiles[ui32Index], DATA_REMOVED );
		}
		m_rFiles.erase( m_rFiles.begin() + ui32Index );
	}
}


void
FileListC::del_file( FileHandleC* pHandle )
{
	for( uint32 i = 0; i < m_rFiles.size(); i++ ) {
		if( m_rFiles[i] == pHandle ) {
			del_file( i );
			break;
		}
	}
}

void
FileListC::clear_list()
{
	m_rFiles.clear();
}


uint32
FileListC::save( SaveC* pSave )
{
	return IO_OK;
}

uint32
FileListC::load( LoadC* pLoad )
{
	return IO_OK;
}
