<?php
/**
 * Items class
 *
 * @package   MyAAC
 * @author    Slawkens <slawkens@gmail.com>
 * @copyright 2017 MyAAC
 * @version   0.5.0
 * @link      http://my-aac.org
 */
defined('MYAAC') or die('Direct access not allowed!');

if ( !function_exists( 'stackId' ) )
{
	function stackId( $count )
	{
		if ( $count >= 50 )
			$stack = 8;
		elseif ( $count >= 25 )
			$stack = 7;
		elseif ( $count >= 10 )
			$stack = 6;
		elseif ( $count >= 5 )
			$stack = 5;
		elseif ( $count >= 4 )
			$stack = 4;
		elseif ( $count >= 3 )
			$stack = 3;
		elseif ( $count >= 2 )
			$stack = 2;
		else
			$stack = 1;

		return $stack;
	}
}

class Items
{
	public static $outputDir = '';
	public static $files = array();

	private static $otb, $dat, $spr;
	private static $lastItem;
	private static $loaded = false;

	public function __destruct()
	{
		if(self::$otb)
			fclose(self::$otb);
		if(self::$dat)
			fclose(self::$dat);
		if(self::$spr)
			fclose(self::$spr);
	}

	public static function generate($id = 100, $count = 1)
	{
		if(!self::$loaded)
			self::load();

		$originalId = $id;
		if($id < 100)
			return false;
			//die('ID cannot be lower than 100.');

		rewind(self::$otb);
		rewind(self::$dat);
		rewind(self::$spr);

		$nostand = false;
		$init = false;
		$originalId = $id;

		// parse info from otb
		while( false !== ( $char = fgetc( self::$otb ) ) )
		{
			$byte = HEX_PREFIX.bin2hex( $char );

			if ( $byte == 0xFE )
				$init = true;
			elseif ( $byte == 0x10 and $init ) {
				extract( unpack( 'x2/Ssid', fread( self::$otb, 4 ) ) );

				if ( $id == $sid ) {
					if ( HEX_PREFIX.bin2hex( fread( self::$otb, 1 ) ) == 0x11 ) {
						extract( unpack( 'x2/Sid', fread( self::$otb, 4 ) ) );
						break;
					}
				}
				$init = false;
			}
		}

		self::$lastItem = array_sum( unpack( 'x4/S*', fread( self::$dat, 12 )));
		if($id > self::$lastItem)
			return false;

		//ini_set('max_execution_time', 300); 
		// parse info from dat
		for( $i = 100; $i <= $id; $i++ ) {
			while( ( $byte = HEX_PREFIX.bin2hex( fgetc( self::$dat ) ) ) != 0xFF ) {
				$offset = 0;
				switch( $byte ) {
					case 0x00:
					case 0x09:
					case 0x0A:
					case 0x1A:
					case 0x1D:
					case 0x1E:
						$offset = 2;
						break;

					case 0x16:
					case 0x19:
						$offset = 4;
						break;

					case 0x01:
					case 0x02:
					case 0x03:
					case 0x04:
					case 0x05:
					case 0x06:
					case 0x07:
					case 0x08:
					case 0x0B:
					case 0x0C:
					case 0x0D:
					case 0x0E:
					case 0x0F:
					case 0x10:
					case 0x11:
					case 0x12:
					case 0x13:
					case 0x14:
					case 0x15:
					case 0x17:
					case 0x18:
					case 0x1B:
					case 0x1C:
					case 0x1F:
					case 0x20:
						break;

					default:
						return false; #trigger_error( sprintf( 'Unknown .DAT byte %s (previous byte: %s; address %x)', $byte, $prev, ftell( $dat ), E_USER_ERROR ) );
						break;
				}

				$prev = $byte;
				fseek( self::$dat, $offset, SEEK_CUR );
			}
			extract( unpack( 'Cwidth/Cheight', fread( self::$dat, 2 ) ) );

			if ( $width > 1 or $height > 1 ) {
				fseek( self::$dat, 1, SEEK_CUR );
				$nostand = true;
			}

			$sprites_c = array_product( unpack( 'C*', fread( self::$dat, 5 ) ) ) * $width * $height;
			$sprites = unpack( 'S*', fread( self::$dat, 2 * $sprites_c ) );
		}

		if ( array_key_exists( stackId( $count ), $sprites ) ) {
			$sprites = (array) $sprites[stackId( $count )];
		}
		else {
			$sprites = (array) $sprites[array_rand( $sprites ) ];
		}

		fseek( self::$spr, 6 );

		$sprite = imagecreatetruecolor( 32 * $width, 32 * $height );
		imagecolortransparent( $sprite, imagecolorallocate( $sprite, 0, 0, 0 ) );

		foreach( $sprites as $key => $value ) {
			fseek( self::$spr, 6 + ( $value - 1 ) * 4 );
			extract( unpack( 'Laddress', fread( self::$spr, 4 ) ) );

			fseek( self::$spr, $address + 3 );
			extract( unpack( 'Ssize', fread( self::$spr, 2 ) ) );

			list( $num, $bit ) = array( 0, 0 );

			while( $bit < $size ) {
				$pixels = unpack( 'Strans/Scolored', fread( self::$spr, 4 ) );
				$num += $pixels['trans'];
				for( $i = 0; $i < $pixels['colored']; $i++ )
				{
					extract( unpack( 'Cred/Cgreen/Cblue', fread( self::$spr, 3 ) ) );

					$red = ( $red == 0 ? ( $green == 0 ? ( $blue == 0 ? 1 : $red ) : $red ) : $red );

					imagesetpixel( $sprite,
						$num % 32 + ( $key % 2 == 1 ? 32 : 0 ),
						$num / 32 + ( $key % 4 != 1 and $key % 4 != 0 ? 32 : 0 ),
						imagecolorallocate( $sprite, $red, $green, $blue ) );

					$num++;
				}

				$bit += 4 + 3 * $pixels['colored'];
			}
		}

		if ( $count >= 2 ) {
			if ( $count > 100 )
				$count = 100;

			$font = 3;
			$length = imagefontwidth( $font ) * strlen( $count );

			$pos = array(
				'x' => ( 32 * $width ) - ( $length + 1 ),
				'y' => ( 32 * $height ) - 13
			);
			imagestring( $sprite, $font, $pos['x'] - 1, $pos['y'] - 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) );
			imagestring( $sprite, $font, $pos['x'], $pos['y'] - 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) );
			imagestring( $sprite, $font, $pos['x'] - 1, $pos['y'], $count, imagecolorallocate( $sprite, 1, 1, 1 ) );

			imagestring( $sprite, $font, $pos['x'], $pos['y'] + 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) );
			imagestring( $sprite, $font, $pos['x'] + 1, $pos['y'], $count, imagecolorallocate( $sprite, 1, 1, 1 ) );
			imagestring( $sprite, $font, $pos['x'] + 1, $pos['y'] + 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) );

			imagestring( $sprite, $font, $pos['x'], $pos['y'], $count, imagecolorallocate( $sprite, 219, 219, 219 ) );
		}

		$imagePath = self::$outputDir . ($count > 1 ? $originalId . '-' . $count : $originalId ) . '.gif';

		// save image
		imagegif($sprite, $imagePath);
	}

	public static function load()
	{
		if(!defined( 'HEX_PREFIX'))
			define('HEX_PREFIX', '0x');

		self::$otb = fopen(self::$files['otb'], 'rb');
		self::$dat = fopen(self::$files['dat'], 'rb');
		self::$spr = fopen(self::$files['spr'], 'rb');

		if(!self::$otb || !self::$dat || !self::$spr)
			die('ERROR: Cannot load data files.');
		/*
		if ( $nostand )
		{
			for( $i = 0; $i < sizeof( $sprites ) / 4; $i++ )
			{
				$sprites = array_merge( (array) $sprites, array_reverse( array_slice( $sprites, $i * 4, 4 ) ) );
			}
		}
		else
		{
			$sprites = (array) $sprites[array_rand( $sprites ) ];
		}
		*/

		self::$loaded = true;
	}

	public static function loaded() {
		return self::$loaded;
	}
}
