#include "ma_oni_d.h"
#include "utools.h"

#define FourCharsToLong( a, b, c, d ) ((d << 24) | (c << 16) | (b << 8) | (a))

char *CMassOniDat::GetIdent( void )
{
	static char Ident[] = "DAT (Oni)";

	return Ident;
}

char *CMassOniDat::GetExtension( void )
{
	static char Ext[] = "dat";
	return Ext;
}

int	 CMassOniDat::CheckFileType( void )
{
	if ( massf == NULL )
		return 0;

	char	buf[ 100 ];
	fseek( massf, 0, SEEK_SET );
	fread( buf, 8, 1, massf );

	if ( UnmassTools::_strcasecmp( MassFileExt, "dat" ) != 0 )
		return 0;

	sprintf( RawFileName, "%s%s.raw", MassFilePath, MassFileName );

//	if ( memcmp( buf, "\x1F\x27\xDC\x33\xDF\xBC\x03\x00", 8 ) == 0 )
//		return 1;
//	if ( memcmp( buf, "\x61\x30\xC1\x23\xDF\xBC\x03\x00", 8 ) == 0 )
//		return 1;
	if ( memcmp( &buf[4], "\xDF\xBC\x03\x00", 4 ) == 0 )
		return 1;

	return 0;
}

void CMassOniDat::GetFileMainInfo( void )
{
	files_count = 0;

	if ( massf == NULL )
		return;

	fseek( massf, 0, SEEK_END );
	filesize = ftell( massf );

	fseek( massf, 0, SEEK_SET );
	fread( &OniDatHeader, 4, 4*4, massf );
	
	files_count		= OniDatHeader.file_list_elements;
	data_start		= OniDatHeader.file_data_offset - 8;
	lib_start = 64;

}

int	 CMassOniDat::ReadRec( long num )
{
	if ( massf == NULL ) 
		return 0;
	if (( (unsigned long)num >= files_count ) && ( num != -1 ))
		return 0;
	if (( num == -1 ) && 
		(( ! next_set ) || ((unsigned long)next_rec_num >= files_count )) )
		return 0;
	
	memset( &FileRec, 0, sizeof( FileRec ) );

	if (( next_set ) && ( (signed)next_rec_num == num ))
		num = -1;

	//seek
	if ( num == -1 ) {
		if ( fseek( massf, next_rec_pos, SEEK_SET ) != 0 )
			return 0;
	}
	else {
		pos = lib_start + SizeOfOniDatRec * num;
		if ( fseek( massf, pos, SEEK_SET ) != 0 )
			return 0;
	}

	//read
	if ( fread( &OniDatRec, SizeOfOniDatRec, 1, massf ) != 1 )
		return 0;

	//set position of the next
	next_rec_pos = ftell( massf );
	if ( num == -1 )
		next_rec_num ++;
	else
		next_rec_num = num + 1;
	if ( num + 1 >= (long)files_count )
		next_set = false;
	else
		next_set = true;
	
	//get info
	num = next_rec_num - 1;

	if ( num == 817 ) {
		num++;
		num--;
	}

	FileRec.offset	= OniDatHeader.file_data_offset + OniDatRec.offset -8;
	FileRec.size	= OniDatRec.size;

	if (( OniDatRec.flags & 1 ) == 0 ) {
		if ( OniDatRec.name_offset > OniDatHeader.name_table_size ) {
			sprintf( error, "ReadRec: seek for filename\n" );
			return 0;
		}

		fseek( massf, OniDatHeader.name_table_offset + OniDatRec.name_offset, SEEK_SET );

		fread( FileRec.type, 1, 4, massf );
		FileRec.type[ 4 ] = 0;

		fread( str, 1, FileNameWithPathMaxLen-1, massf );
		i = strlen( str );
//		while (( str[ i-1 ] != '/' ) && ( str[ i-1 ] != '\\' ) && ( i > 0 ))
//			i--;
		while ( i > 0 ) {
			if(( str[ i-1 ] == '/' ) || ( str[ i-1 ] == '\\' ))
				str[ i-1 ] = '!';
			i--;
		}

//		strcpy( str2, &str[ i ] );
//		str[ i ] = 0;

//		sprintf( FileRec.name, "%s%05lu-%s", str, num, str2 );
		sprintf( FileRec.name, "%05lu-%s", num, str );

		pos = strlen( FileRec.name );
		FileRec.name[ pos ] =  '.';
		FileRec.name[ pos + 1 ] = OniDatRec.type[3];
		FileRec.name[ pos + 2 ] = OniDatRec.type[2];
		FileRec.name[ pos + 3 ] = OniDatRec.type[1];
		FileRec.name[ pos + 4 ] = OniDatRec.type[0];
		FileRec.name[ pos + 5 ] = 0;
		FileRec.name[ FileNameWithPathMaxLen-1 ] = 0;
	}
	else {
		sprintf( FileRec.type, "%c%c%c%c",
			OniDatRec.type[ 3 ], OniDatRec.type[ 2 ], 
			OniDatRec.type[ 1 ], OniDatRec.type[ 0 ] );
		sprintf( FileRec.name, "%05lu-.%s", num, FileRec.type );
	}

	FileRec.flaga[0] = FileRec.size;

	if (( OniDatRec.flags & 2 ) == 0 ) {
		//uprava, podla typu musim priratat aj data s RAW suboru
		switch( OniDatRec.typel ) {
			case FourCharsToLong( 'P', 'M', 'X', 'T' ):
				//pridam k velkosti velkost bitmapy.
				fseek( massf, FileRec.offset, SEEK_SET );
				fread( &TXMP_structure, 1, sizeof( TXMP_structure ), massf );
				switch( TXMP_structure.format ) {
				case 0:
				case 1:
				case 2:
					FileRec.size += TXMP_structure.width * TXMP_structure.height * 2;
					break;
				case 8:
					FileRec.size += TXMP_structure.width * TXMP_structure.height * 4;
					break;
				case 9:
					FileRec.size += TXMP_structure.width * TXMP_structure.height / 2;
					break;
				}//switch
				FileRec.flaga[1] = TXMP_structure.dataOffset;
				break;
		}
	}//flag != 2, (no data)

	FileRec.set = 1;

	return 1;
}

int CMassOniDat::GetFlags( void )
{
	return ma_flag_fills_type;
}

unsigned long CMassOniDat::Extract( unsigned long offset, unsigned long size, unsigned char *output )
{
	if ( massf == NULL )
		return 0;

	unsigned long	s, c, p;
	// vo FileRec.flaga[0] je velkost headra, v [1] je offset raw dat


	//nacitam header
	if ( offset < FileRec.flaga[0] ) {
		s = offset; c = size;
		if ( s + c > FileRec.flaga[0] )
			c = FileRec.flaga[0] - s;
		if ( fseek( massf, FileRec.offset + s, SEEK_SET ) != 0 )
			return 0;
		if ( fread( output, c, 1, massf ) != 1 )
			return 0;
	}
	
	//nacitam data z raw suboru
//	if (( FileRec.flaga[0] < FileRec.size ) && ( offset + size >= FileRec.flaga[0] )) {
	if ( FileRec.flaga[0] < FileRec.size ) {
		fraw = fopen( RawFileName, "rb" );
		if ( fraw == NULL )
			return 0;

		if ( offset < FileRec.flaga[0] ) {
			s = FileRec.flaga[1];
			c = offset + size - FileRec.flaga[0];
			p = FileRec.flaga[0] - offset;
		}
		else {
			s = FileRec.flaga[1] + offset - FileRec.flaga[0];
			c = size;
			p = 0;
		}

		if ( fseek( fraw, s, SEEK_SET ) != 0 )
			return 0;
		if ( fread( &output[ p ], c, 1, fraw ) != 1 )
			return 0;

		fclose( fraw );		
	}
		
	return size;
}
