/*
Ghostly drop triggering the Nautilus teardrop maze
*/

"use strict";

var GO_TearTrap = function(){
	this.sprite = new Sprite(GO_TearTrap.spriteSheet,"TearTrap");
	this.sprite.collision_flags = 
		DEFINE_SPRITE_COLLISION_FLAGS.SPRITES_PASSIVE;
	this.sprite.setBoundingBox(4,2,10,13);
	this.sprite.game_object = this; // no longer a generic GO
		
	this.frame_timer=0;
};
GO_TearTrap.spriteImg = SDS_Load_Image("art/sheets/sprite/teartrap.png");
GO_TearTrap.spriteSheet = new TileSheet(4, 4, 2, 2, GO_TearTrap.spriteImg);

GO_TearTrap.prototype = new GameObject(
	new Sprite(
		GO_TearTrap.spriteSheet,
		"TearTrap"
	),
	"TearTrap"
	);
	
	GO_TearTrap.prototype.interactions = 
		DEFINE_GAMEOBJECT_INTERACTIONS.COLLECT;
	
	GO_TearTrap.prototype._getNeighbors = function(stack,current,maze,out){
		out.length=0;
		if (!stack.length) return;
		current = {x:stack[stack.length-1].x, y:stack[stack.length-1].y};

		if (current.y>0 && !maze[current.y-1][current.x]) out.push(1);
		//if (current.x<this._heap.mwidth-1 && !maze[current.y][current.x+1]) n.push(2);
		if (current.x<maze[current.y].length-1 && !maze[current.y][current.x+1]) out.push(2);
		//if (current.y<this._heap.mheight-1 && !maze[current.y+1][current.x]) n.push(4);
		if (current.y<maze.length-1 && !maze[current.y+1][current.x]) out.push(4);
		if (current.x>0 && !maze[current.y][current.x-1]) out.push(8);
		return;
	};
	GO_TearTrap.prototype._dir = 0;
	GO_TearTrap.prototype._knockOut = function(stack,current,maze,furthest){
		if (!stack.length) return;
		var n=[]; // virtually unavoidable alloc
		this._getNeighbors(stack,current,maze,n);
		while (stack.length && n.length){
			current.x=stack[stack.length-1].x;
			current.y=stack[stack.length-1].y;

			GO_TearTrap.prototype._dir = n[Math.floor(Math.random()*n.length)];
			maze[current.y][current.x]|=GO_TearTrap.prototype._dir;
			switch(GO_TearTrap.prototype._dir){
				case 1:
					current.y--;
					maze[current.y][current.x]|=4;
				break;
				case 2:
					current.x++;
					maze[current.y][current.x]|=8;
				break;
				case 4:
					current.y++;
					maze[current.y][current.x]|=1;
				break;
				case 8:
					current.x--;
					maze[current.y][current.x]|=2;
				break;
			}
			stack.push({x:current.x,y:current.y}); // nearly impossible to avoid dynamic alloc in recursion
			if (stack.length>furthest.dist){
				furthest.x=current.x;
				furthest.y=current.y;
				furthest.dist = stack.length;
			}
			this._knockOut(stack,current,maze,furthest);// recurse
			this._getNeighbors(stack,current,maze,n);
		}
		
		if (stack.length){
			stack.pop();
		}
		return;
	};
	GO_TearTrap.prototype._getDestName = function(){return "nautilus_tail_A";};
	GO_TearTrap.prototype._relocate = function(sprite){
			//sprite.x = sprite.x;
			//sprite.y = sprite.y;
			GLOBAL_SCRATCHPAD.note("flash",true);
			GLOBAL_SCRATCHPAD.persist("flash");
		};

	GO_TearTrap.prototype.collect = function(sourceGO){
		// Go-go Gadget CS-100 Maze Generator!
		this._heap.mwidth = 7;
		this._heap.mheight = 5;
		this._heap.mscale = 48;
		this._heap.moffset = {x:(2<<4)+8, y:(5<<4)+8}; // on grid center, i.e. not tile upper-left
		if (!this._heap.maze) this._heap.maze = [];
		this._heap.maze.length=0;

		for (this._heap.i=0; this._heap.i<this._heap.mheight; ++this._heap.i){
			this._heap.row = []; // yes, we do kinda really need a new array for each row.
			for (this._heap.j=0; this._heap.j<this._heap.mwidth; ++this._heap.j){
				this._heap.row.push(0);
			}
			this._heap.maze.push(this._heap.row);
		}
		this._heap.row = null;
		if (!this._heap.start) this._heap.start={};
		this._heap.start.x=this._heap.mwidth>>1;
		this._heap.start.y=this._heap.mheight>>1;

		if (!this._heap.current) this._heap.current={};
		this._heap.current.x=this._heap.start.x;
		this._heap.current.y=this._heap.start.y;

		if (!this._heap.furthest) this._heap.furthest={};
		this._heap.furthest.x=this._heap.current.x;
		this._heap.furthest.y=this._heap.current.y;
		this._heap.furthest.dist = 0;
		
		if (!this._heap.stack) this._heap.stack = [];
		this._heap.stack.length=0;

		this._heap.stack.push( {x:this._heap.current.x,y:this._heap.current.y} ); // kinda difficult to avoid dynamic allocation here...
		// direction flags: 1=up, 2=right, 4=down, 8=left
		//var getNeighbors = function(){
		//	if (!this._heap.stack.length) return [];
		//	this._heap.current = {x:this._heap.stack[this._heap.stack.length-1].x, y:this._heap.stack[this._heap.stack.length-1].y};
		//
		//	var n = [];
		//	if (this._heap.current.y>0 && !this._heap.maze[this._heap.current.y-1][this._heap.current.x]) n.push(1);
		//	if (this._heap.current.x<this._heap.mwidth-1 && !this._heap.maze[this._heap.current.y][this._heap.current.x+1]) n.push(2);
		//	if (this._heap.current.y<this._heap.mheight-1 && !this._heap.maze[this._heap.current.y+1][this._heap.current.x]) n.push(4);
		//	if (this._heap.current.x>0 && !this._heap.maze[this._heap.current.y][this._heap.current.x-1]) n.push(8);
		//	return n;
		//}
		//var knockOut = function(){
		//	if (!this._heap.stack.length) return;
		//	var n=[];
		//	this._getNeighbors(this._heap.stack,this._heap.current,this._heap.maze,n);
		//	while (this._heap.stack.length && n.length){
		//		this._heap.current = {x:this._heap.stack[this._heap.stack.length-1].x, y:this._heap.stack[this._heap.stack.length-1].y};
		//
		//		var dir = n[Math.floor(Math.random()*n.length)];
		//		this._heap.maze[this._heap.current.y][this._heap.current.x]|=dir;
		//		switch(dir){
		//			case 1:
		//				this._heap.current.y--;
		//				this._heap.maze[this._heap.current.y][this._heap.current.x]|=4;
		//			break;
		//			case 2:
		//				this._heap.current.x++;
		//				this._heap.maze[this._heap.current.y][this._heap.current.x]|=8;
		//			break;
		//			case 4:
		//				this._heap.current.y++;
		//				this._heap.maze[this._heap.current.y][this._heap.current.x]|=1;
		//			break;
		//			case 8:
		//				this._heap.current.x--;
		//				this._heap.maze[this._heap.current.y][this._heap.current.x]|=2;
		//			break;
		//		}
		//		this._heap.stack.push({x:this._heap.current.x,y:this._heap.current.y});
		//		if (this._heap.stack.length>this._heap.furthestdist){
		//			this._heap.furthest.x=this._heap.current.x;
		//			this._heap.furthest.y=this._heap.current.y;
		//			this._heap.furthestdist = this._heap.stack.length;
		//		}
		//		knockOut();// recurse
		//		this._getNeighbors(this._heap.stack,this._heap.current,this._heap.maze,n);
		//	}
		//	
		//	if (this._heap.stack.length){
		//		this._heap.stack.pop();
		//	}
		//	return;
		//	
		//}

		this._knockOut(this._heap.stack,this._heap.current,this._heap.maze,this._heap.furthest);

		this._heap.ddrop = null;
		for (this._heap.i=0; this._heap.i<this._heap.mheight; ++this._heap.i){
			for (this._heap.j=0; this._heap.j<this._heap.mwidth; ++this._heap.j){
				if (this._heap.j<this._heap.mwidth-1 && !(this._heap.maze[this._heap.i][this._heap.j]&2)){
					this._heap.ddrop = new GO_DarkDrop();
					this._heap.ddrop.sprite.x = ((this._heap.j+1)*this._heap.mscale)+this._heap.moffset.x - ((this._heap.ddrop.sprite.box_left+this._heap.ddrop.sprite.box_right)>>1);
					this._heap.ddrop.sprite.y = (this._heap.i*this._heap.mscale)+this._heap.moffset.y + (this._heap.mscale>>1) - ((this._heap.ddrop.sprite.box_top+this._heap.ddrop.sprite.box_bottom)>>1);
					this.sprite.map_room.addSprite(this._heap.ddrop.sprite);
					this.manager.add(this._heap.ddrop);
				}
				if (this._heap.i<this._heap.mheight-1 && !(this._heap.maze[this._heap.i][this._heap.j]&4)){
					this._heap.ddrop = new GO_DarkDrop();
					this._heap.ddrop.sprite.x = (this._heap.j*this._heap.mscale)+this._heap.moffset.x + (this._heap.mscale>>1) - ((this._heap.ddrop.sprite.box_left+this._heap.ddrop.sprite.box_right)>>1);
					this._heap.ddrop.sprite.y = ((this._heap.i+1)*this._heap.mscale)+this._heap.moffset.y - ((this._heap.ddrop.sprite.box_top+this._heap.ddrop.sprite.box_bottom)>>1);
					this.sprite.map_room.addSprite(this._heap.ddrop.sprite);
					this.manager.add(this._heap.ddrop);
				}		
			}
		}
		this._heap.ddrop = null;//pending pooling

		this._heap.door = new GO_GhostVortex(true,this._getDestName,this._relocate);
		this._heap.door.sprite.x = (this._heap.furthest.x*this._heap.mscale)+this._heap.moffset.x + (this._heap.mscale>>1) - ((this._heap.door.sprite.box_left+this._heap.door.sprite.box_right)>>1);
		this._heap.door.sprite.y = (this._heap.furthest.y*this._heap.mscale)+this._heap.moffset.y + (this._heap.mscale>>1) - ((this._heap.door.sprite.box_top+this._heap.door.sprite.box_bottom)>>1);
		this.sprite.map_room.addSprite(this._heap.door.sprite);
		this.manager.add(this._heap.door);
		this._heap.door=null;//pending pooling

		this.sprite.map_room.removeSprite(this.sprite);
		this.manager.remove(this);
		return null;
	};

	GO_TearTrap.prototype.Update = function(){
		this.frame_timer++;
		this.frame_timer&=15;
		this.sprite.frame = this.frame_timer>>2;
		
		//this.sprite.frame = this.frame_timer&1 ? 15 : this.sprite.frame;
		this.sprite.visible = !(this.frame_timer&1);
	};
