package com.terry.engine {
	import flash.display.*;
	import flash.geom.*;
  import flash.events.*;
  import flash.net.*;
	import flash.text.*;
	import gamecontrol.control;
	
	public class gfx {
		public static function init():void {
			initgfx();
			font.init();
    }
		
		//Initialise arrays here
		public static function initgfx():void {
			//We initialise a few things
			screenwidth = def.SCREENWIDTH; screenheight = def.SCREENHEIGHT;
			screenwidthmid = screenwidth / 2; screenheightmid = screenheight / 2;
			screenviewwidth = screenwidth; screenviewheight = screenheight;
			
			tiles_rect = new Rectangle(0, 0, def.TILESIZE, def.TILESIZE);
			sprites_rect = new Rectangle(0, 0, def.SPRITESIZE, def.SPRITESIZE);
			trect = new Rectangle; tpoint = new Point();
			tbuffer = new BitmapData(1, 1, true);
			ct = new ColorTransform(0, 0, 0, 1, 255, 255, 255, 1); //Set to white
			temptile = new BitmapData(def.TILESIZE, def.TILESIZE, true, 0x000000);
			temptile2 = new BitmapData(def.TILESIZE, def.TILESIZE, false, 0x000000);
			fademode = 0; fadeamount = 0; fadeaction = 0;
			
			//Scaling stuff
			bigbuffer = new BitmapData(screenwidth, 32, true, 0x000000);
			bigbufferscreen = new Bitmap(bigbuffer);
			bigbufferscreen.width = screenwidth * 2;
			bigbufferscreen.height = 64;
			scaleMatrix = new Matrix();
			
			backbuffer = new BitmapData(screenwidth, screenheight, false, 0x000000);
			screenbuffer = new BitmapData(screenwidth, screenheight, false, 0x000000);
			textboxbuffer = new BitmapData(screenwidth, screenheight, false, 0x00000000);
			
			screen = new Bitmap(screenbuffer);
			screen.width = screenwidth * def.SCREENSCALE;
			screen.height = screenheight * def.SCREENSCALE;
		}
		
		public static function settrect(x:int, y:int, w:int, h:int):void {
			trect.x = x;
			trect.y = y;
			trect.width = w;
			trect.height = h;
		}
		
		public static function settpoint(x:int, y:int):void {
			tpoint.x = x;
			tpoint.y = y;
		}
		
		public static function maketilearray():void {
			for (var j:int = 0; j < 50; j++) {
				for (var i:int = 0; i < 20; i++) {
					var t:BitmapData = new BitmapData(def.TILESIZE, def.TILESIZE, true, 0x000000);
					settrect(i * def.TILESIZE, j * def.TILESIZE, def.TILESIZE, def.TILESIZE);
					var temprect:Rectangle = trect;	
					t.copyPixels(buffer, temprect, tl);
					tiles.push(t);
				}
			}
		}	
		
		public static function makespritearray():void {
			for (var k:int = 0; k < control.numitems; k++) {
				var t:BitmapData = new BitmapData(def.TILESIZE * control.items[k].size.x, def.TILESIZE * control.items[k].size.y, true, 0x000000);
				for (var j:int = 0; j < control.items[k].size.y; j++) {
					for (var i:int = 0; i < control.items[k].size.x; i++) {
						settpoint(i * 16, j * 16);
						t.copyPixels(tiles[control.items[k].tile + i + (j * 20)], tiles_rect, tpoint);
					}
				}
				sprites.push(t);
			}
			
			//Right at the end, add the bin as well!
			t = new BitmapData(def.TILESIZE * 2, def.TILESIZE * 3, true, 0x000000);
			for (j = 0; j < 3; j++) {
				for (i = 0; i < 2; i++) {
					settpoint(i * 16, j * 16);
					t.copyPixels(tiles[618 + i + (j * 20)], tiles_rect, tpoint);
				}
			}
			
			sprites.push(t);
			
			t = new BitmapData(def.TILESIZE * 2, def.TILESIZE * 2, true, 0x000000);
			//And background spinny thing!
			for (j = 0; j < 2; j++) {
				for (i = 0; i < 2; i++) {
					settpoint(i * 16, j * 16);
					t.copyPixels(tiles[678 + i + (j * 20)], tiles_rect, tpoint);
				}
			}
			
			sprites.push(t);
		}
		
		public static function addimage():void {
			var t:BitmapData = new BitmapData(buffer.width, buffer.height, true, 0x000000);
			settrect(0, 0, buffer.width, buffer.height);			
			t.copyPixels(buffer, trect, tl);
			images.push(t);
		}
		
		// Draw Primatives
		public static function drawline(x1:int, y1:int, x2:int, y2:int, r:int, g:int, b:int):void {
			tempshape.graphics.clear();
			tempshape.graphics.lineStyle(1, RGB(r, g, b));
			tempshape.graphics.lineTo(x2 - x1, y2 - y1);
			
			shapematrix.translate(x1, y1);
			backbuffer.draw(tempshape, shapematrix);
			shapematrix.translate(-x1, -y1);
		}

		public static function drawbox(x1:int, y1:int, w1:int, h1:int, r:int, g:int, b:int):void {
			if (w1 < 0) {
				w1 = -w1;
				x1 = x1 - w1;
			}
			if (h1 < 0) {
				h1 = -h1;
				y1 = y1 - h1;
			}
			settrect(x1, y1, w1, 1); backbuffer.fillRect(trect, RGB(r, g, b));
			settrect(x1, y1 + h1 - 1, w1, 1); backbuffer.fillRect(trect, RGB(r, g, b));
			settrect(x1, y1, 1, h1); backbuffer.fillRect(trect, RGB(r, g, b));
			settrect(x1 + w1 - 1, y1, 1, h1); backbuffer.fillRect(trect, RGB(r, g, b));
		}

		public static function cls():void {
			fillrect(0, 0, screenwidth, screenheight, 0, 0, 0);
		}

		public static function fillrect(x1:int, y1:int, w1:int, h1:int, r:int, g:int, b:int):void {
			settrect(x1, y1, w1, h1);
			backbuffer.fillRect(trect, RGB(r, g, b));
		}
		
		public static function drawimage(t:int, xp:int, yp:int, cent:Boolean=false):void {
			if (cent) {
				settrect(0, 0, images[t].width, images[t].height);
				settpoint(80 - int(images[t].width / 2), yp);
				backbuffer.copyPixels(images[t], trect, tpoint);
			}else {
				settrect(0, 0, images[t].width, images[t].height);
				settpoint(xp, yp);
				backbuffer.copyPixels(images[t], trect, tpoint);
			}
		}
		
		public static function drawbuffertile(x:int, y:int, t:int):void {
			settpoint(x, y);
			buffer.copyPixels(tiles[t], tiles_rect, tpoint);
		}
		
		public static function drawtile(x:int, y:int, t:int):void {
			settpoint(x, y);
			backbuffer.copyPixels(tiles[t], tiles_rect, tpoint);
		}
		
		
		public static function drawtilealpha(xp:int, yp:int, t:int, a:Number):void {
			/*a = 0.5;
			alphamult = 0xFF * a;
			
			settrect(xp, yp, 16, 16); temptile.copyPixels(backbuffer, trect, tl);
			temptile2.copyPixels(backbuffer, trect, tl);
			temptile2.copyPixels(tiles[t + 3], tiles[t].rect, tl);
			
			temptile.merge(tiles[t], tiles[t].rect, tl, alphamult, alphamult, alphamult, alphamult);	
			
			
			settpoint(xp, yp); 
			backbuffer.copyPixels(temptile, temptile.rect, tpoint);
			backbuffer.copyPixels(temptile2, temptile.rect, tpoint);
			*/
			
			settpoint(xp, yp -50 + int(a * 50.0));
			backbuffer.copyPixels(tiles[t], tiles_rect, tpoint);
		}
		
		public static function drawsprite(x:int, y:int, t:int, rot:int, transx:int, transy:int):void {
			scaleMatrix.translate(-transx, -transy);
			scaleMatrix.rotate((rot * 3.1415) / 180);
			if (t <= control.numitems) {
				scaleMatrix.scale(1.5 + (Number(help.fastglow)/400), 1.5+ (Number(help.fastglow)/400));	
			}
			scaleMatrix.translate(x + transx, y + transy);
			
			backbuffer.draw(sprites[t], scaleMatrix);
			scaleMatrix.identity();
		}
		
		public static function bigdrawtile(x:int, y:int, t:int, sc:Number = 2):void {
			scaleMatrix.scale(sc, sc);
			
			bigbuffer.fillRect(bigbuffer.rect, 0x000000);
			settpoint(0, 0);
			bigbuffer.copyPixels(tiles[t], tiles_rect, tpoint);				
			scaleMatrix.translate(x, y);
			backbuffer.draw(bigbufferscreen, scaleMatrix);
			scaleMatrix.identity();
		}
		
		public static function bigdrawsprite(x:int, y:int, t:int, rot:int, transx:int, transy:int, sc:Number = 2):void {
			scaleMatrix.translate(-transx, -transy);
			scaleMatrix.rotate((rot * 3.1415) / 180);
			scaleMatrix.scale(sc, sc);
			scaleMatrix.translate(x + transx, y + transy);
			
			backbuffer.draw(sprites[t], scaleMatrix);
			scaleMatrix.identity();
		}
		
		public static function drawtile_col(x:int, y:int, t:int, col:int):void {
			scaleMatrix.translate(x, y);
			ct.color = col;
			backbuffer.draw(tiles[t], scaleMatrix, ct);
			scaleMatrix.identity();
		}
		
		public static function drawsprite_col(x:int, y:int, t:int, rot:int, transx:int, transy:int, col:int):void {
			scaleMatrix.translate(-transx, -transy);
			scaleMatrix.rotate((rot * 3.1415) / 180);
			scaleMatrix.translate(x + transx, y + transy);
			
			ct.color = col;
			backbuffer.draw(sprites[t], scaleMatrix, ct);
			scaleMatrix.identity();
		}
		
		public function bigdrawtile_col(x:int, y:int, t:int, sc:Number, col:int):void {
			scaleMatrix.scale(sc, sc);
			
			bigbuffer.fillRect(bigbuffer.rect, 0x000000);
			settpoint(0, 0);
			bigbuffer.copyPixels(tiles[t], tiles_rect, tpoint);				
			scaleMatrix.translate(x, y);
			
			ct.color = col;
			backbuffer.draw(bigbufferscreen, scaleMatrix, ct);
			scaleMatrix.identity();
		}
		
		public static function bigdrawsprite_col(x:int, y:int, t:int, rot:int, transx:int, transy:int, sc:Number, col:int):void {
			scaleMatrix.translate(-transx, -transy);
			scaleMatrix.rotate((rot * 3.1415) / 180);
			scaleMatrix.scale(sc, sc);
			scaleMatrix.translate(x + transx, y + transy);
			
			ct.color = col;
			backbuffer.draw(sprites[t], scaleMatrix, ct);
			scaleMatrix.identity();
		}
		
		public static function draw_default(i:int):void {
			settpoint(obj.entities[i].xp, obj.entities[i].yp);
			backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
		}
		
		public static function draw_defaultinit(i:int, xoff:int, yoff:int, t:int):void {
			drawsprite(obj.initentities[i].xp - xoff, obj.initentities[i].yp - yoff, t, 0, 0, 0);
		}
		
		public static function drawentities():void {	
			var i:int = 0;
			if (obj.nentity > 2) {
				i = 2;
				obj.animateentities(i);
				if (obj.entities[i].active) {
					if (!obj.entities[i].invis) {
					  obj.templates[obj.entindex[obj.entities[i].type]].draw(i);
					}
				}
				
				i = 0;
				if(obj.entities[0].yp > obj.entities[1].yp) i = 1;
				obj.animateentities(i);
				if (obj.entities[i].active) {
					if (!obj.entities[i].invis) {
					  obj.templates[obj.entindex[obj.entities[i].type]].draw(i);
					}
				}
				
				i = 1 - i;
				obj.animateentities(i);
				if (obj.entities[i].active) {
					if (!obj.entities[i].invis) {
					  obj.templates[obj.entindex[obj.entities[i].type]].draw(i);
					}
				}
			}else if (obj.nentity > 1) {
				i = 0;
				if(obj.entities[0].yp > obj.entities[1].yp) i = 1;
				obj.animateentities(i);
				if (obj.entities[i].active) {
					if (!obj.entities[i].invis) {
					  obj.templates[obj.entindex[obj.entities[i].type]].draw(i);
					}
				}
				
				i = 1 - i;
				obj.animateentities(i);
				if (obj.entities[i].active) {
					if (!obj.entities[i].invis) {
					  obj.templates[obj.entindex[obj.entities[i].type]].draw(i);
					}
				}
			}else {
				i = 0;
				obj.animateentities(i);
				if (obj.entities[i].active) {
					if (!obj.entities[i].invis) {
					  obj.templates[obj.entindex[obj.entities[i].type]].draw(i);
					}
				}
			}
		}
		
		//Fade functions
		public static function processfade():void {
			if (fademode > def.FADED_OUT) {
				if (fademode == def.FADE_OUT) {
					//prepare fade out
					fadeamount = 0;
					fademode = def.FADING_OUT;
				}else if (fademode == def.FADING_OUT) {
					fadeamount += 5;
					if (fadeamount > 100) {
						fademode = def.FADED_OUT; //faded
					}
				}else if (fademode == def.FADE_IN) {
					//prepare fade in
					fadeamount = 100;
					fademode = def.FADING_IN;
				}else if (fademode == def.FADING_IN) {
					fadeamount -= 5;
					if (fadeamount <= 0) {
						fademode = def.FADED_IN; //normal
					}
				}
			}
		}
		
		public static function getred(c:uint):uint {
			return (( c >> 16 ) & 0xFF);
		}
		
		public static function getgreen(c:uint):uint {
			return ( (c >> 8) & 0xFF );
		}
		
		public static function getblue(c:uint):uint {
			return ( c & 0xFF );
		}
		
		public static function RGB(red:uint, green:uint, blue:uint):uint {
			return (blue | (green << 8) | (red << 16));
		}
		
		public static function RGBA(red:uint, green:uint, blue:uint):uint {
			return (blue | (green << 8) | (red << 16)) + 0xFF000000;
		}
		
		//Text functions
		public static function rprint(x:int, y:int, t:String, r:int, g:int, b:int):void {
			font.rprint(x, y, t, r, g, b);
		}
		
		public static function print(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false):void {
		  font.print(x, y, t, r, g, b, cen);
		}
		
		public static function len(t:String, sz:int = 1):int {
			return font.len(t, sz);
		}
		
		public static function hig(t:String, sz:int = 1):int {
			return font.hig(t, sz);
		}
		
		public static function rbigprint(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false, sc:Number = 2):void {
			font.rbigprint(x, y, t, r, g, b, cen, sc);
		}
		
		public static function bigprint(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false, sc:Number = 2):void {
			font.bigprint(x, y, t, r, g, b, cen, sc);
		}
		
		public static var textbubblex:int;
		public static function drawgui():void {
			textbox.textboxcleanup();
			//Draw all the textboxes to the screen
			for (var i:int = 0; i < textbox.ntextbox; i++) {
				if (textbox.tb[i].active) {
					drawtextbox(textbox.tb[i].xp, 
											textbox.tb[i].yp, 
											textbox.tb[i].w, 
											textbox.tb[i].h, 
											textbox.tb[i].col, textbox.tb[i].tl);
					if (textbox.tb[i].textboxstate >= 2 && textbox.tb[i].textboxstate < 4) {
						var j:int;
						if (textbox.tb[i].showname) {
							for (j = 0; j < textbox.tb[i].numlines; j++) {
								if (j == 0) {
									font.print(textbox.tb[i].xp + 14, 
														 textbox.tb[i].yp + 6, 
														 textbox.tb[i].line[j], 255, 255, 0);
								}else {
									textbox.tbprint(j, textbox.tb[i].tbline, textbox.tb[i].tbcursor, 
																	textbox.tb[i].xp + 22, 
																	textbox.tb[i].yp + 6, 
																	textbox.tb[i].line[j], 0, 0, 0);					
								}
							}
						}else {
							linekludge = 0;
							if (textbox.tb[i].numlines == 1) { 				linekludge = -3;
							}else if (textbox.tb[i].numlines == 2) {  linekludge = -1;
							}else if (textbox.tb[i].numlines == 3) {  linekludge = 1;
							}else if (textbox.tb[i].numlines == 4) {  linekludge = 3;
							}else if (textbox.tb[i].numlines == 5) {  linekludge = -3;
							}else if (textbox.tb[i].numlines == 6) {  linekludge = -1;
							}
							for (j = 0; j < textbox.tb[i].numlines; j++) {
								textbox.tbprint(j, textbox.tb[i].tbline, textbox.tb[i].tbcursor, 
																textbox.tb[i].xp + 14, 
																textbox.tb[i].yp + 6 + linekludge, 
																textbox.tb[i].line[j], 0, 0, 0);					
							}
						}
					}
				}
			}
		}
		
		public static var linekludge:int;
		
		//Render functions
		public static function normalrender():void {
			backbuffer.unlock();
			
			screenbuffer.lock();
			screenbuffer.copyPixels(backbuffer, backbuffer.rect, tl, null, null, false);
			screenbuffer.unlock();
			
			backbuffer.lock();
		}

		public static function screenrender():void {
			if (game.test) print(5, 5, game.teststring, 196, 196, 196, false);
			
			if (flashlight > 0) { flashlight--; gfxflashlight(); }
			if (screenshake > 0) {	screenshake--;	gfxscreenshake();}else{
				normalrender();
			}
		}
		
		public static var screenwidth:int, screenheight:int;
		public static var screenwidthmid:int, screenheightmid:int;
		public static var screenviewwidth:int, screenviewheight:int;
		
		public static var images:Vector.<BitmapData> = new Vector.<BitmapData>;
		public static var tiles:Vector.<BitmapData> = new Vector.<BitmapData>;
		public static var sprites:Vector.<BitmapData> = new Vector.<BitmapData>;
		public static var ct:ColorTransform;
	  public static var tiles_rect:Rectangle;
	  public static var sprites_rect:Rectangle;
		public static var images_rect:Rectangle;
	  public static var tl:Point = new Point(0, 0);
		public static var trect:Rectangle, tpoint:Point, tbuffer:BitmapData;
		
		public static var buffer:BitmapData;
		
		public static var temptile:BitmapData;
		public static var temptile2:BitmapData;
		//Actual backgrounds
		public static var backbuffer:BitmapData;
		public static var screenbuffer:BitmapData;
		public static var screen:Bitmap;
		//Sprite Scaling Stuff
		public static var bigbuffer:BitmapData;
		public static var bigbufferscreen:Bitmap;
		public static var scaleMatrix:Matrix = new Matrix();
		//Tempshape
		public static var tempshape:Shape = new Shape();
		public static var shapematrix:Matrix = new Matrix();
		//Fade Transition (room changes, game state changes etc)
		public static var fademode:int, fadeamount:int, fadeaction:int;
		
		public static var screenshake:int, flashlight:int;
				
		public static var alphamult:uint;
		public static var textboxbuffer:BitmapData;
	  
		//Proper gfxclass starts here
		include "../../../config/style.as";
	}
}