"use strict";

//var DEFINE_SMOKE_SPEEDS = {
//		COUGH: [4,3,3,3,3,2,2,2,2,1,1,1,1],
//		VENT: [2,2,2,2,2,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1],
//	};
var GO_Smoke = function(speed,silent,hold_time){
	silent = (typeof(silent)==='undefined' || silent==null) ? false : silent;
	
	this.sprite = new Sprite(GO_Smoke.spriteSheet,"Smoke");
	this.sprite.collision_flags = 
		DEFINE_SPRITE_COLLISION_FLAGS.SPRITES_PASSIVE |
		DEFINE_SPRITE_COLLISION_FLAGS.SPRITES_ACTIVE;
	this.sprite.setBoundingBox(
		4,
		4,
		11,
		11);
	//this.sprite.constraints=constraints;
	this.sprite.max_step = 2;
	this.sprite.game_object = this; // no longer a generic GO

	this.host_obj = null; // a GO_Enemy, if any, which emitted this Smoke.  Must have a .removeSmoke(smoke) and a .infect() call

	this.frame_timer = 0;

	this.state = "launch";// launch, idle, return, dissipate
	this.state_timer=0;
	this.launch_dir = {x:1, y:0};
	this.launch_speed = speed ? speed : GO_Smoke.SPEEDS.COUGH;

	this.dissipated=false;

	this.hold_time = (typeof(hold_time)==='undefined' || hold_time==null) ? 60 : hold_time;

	this.sfx = new Chiptune("FX_cough",SDS.sfxchip);
	
	if (!silent){
		this.sfx.play(false);
	}

	this._heap.collisions = [];

};
GO_Smoke.spriteImg = SDS_Load_Image("art/sheets/sprite/smoke.png");
GO_Smoke.spriteSheet = new TileSheet(4, 4, 2, 2, GO_Smoke.spriteImg);
GO_Smoke.SPEEDS = {
		COUGH: [4,3,3,3,3,2,2,2,2,1,1,1,1],
		VENT: [2,2,2,2,2,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1],
		APPEAR: [],
	};

GO_Smoke.prototype = new GameObject(
	new Sprite(
		GO_Smoke.spriteSheet,
		"Smoke"
	),
	"Smoke"
	);

	GO_Smoke.prototype.interactions = 
		DEFINE_GAMEOBJECT_INTERACTIONS.DAMAGE |
		DEFINE_GAMEOBJECT_INTERACTIONS.INFLICT;

	GO_Smoke.prototype.idle_frames = [0,1,2,3,2,1];
	GO_Smoke.prototype.dissipate_frames = [4,5,6,7];
	GO_Smoke.prototype.launch_frames = [8,9,10,11,0];

	GO_Smoke.prototype.damage = function(source,points){
		this.dissipate();
		return true; // don't break rocks...
	};
	GO_Smoke.prototype._inflictVal = {hp:0, chi:8};
	GO_Smoke.prototype.inflict = function(){
		this.dissipate();

		return this._inflictVal;
	};

	GO_Smoke.prototype.dissipate = function(){
		if (this.state!="dissipate"){
			this.state="dissipate";
			this.state_timer = 0;
			this.frame_timer = 0;
			this.interactions = 0;
		}
	};

	GO_Smoke.prototype.Update = function(){
		this._heap.dx=0;
		this._heap.dy=0;
		this._heap.spriteMoveRes.init(0, null, null, null, null);
		switch (this.state){
			case "launch":
				if (this.state_timer<this.launch_speed.length){
					// move, but don't set moveRes so we don't hit our host on the way out
					this.sprite.move(
						this.launch_dir.x * this.launch_speed[this.state_timer],
						this.launch_dir.y * this.launch_speed[this.state_timer]);
				}
				else{
					this.state="idle";
					this.state_timer=0;
				}
			break;
			case "idle":
				
				// if our host comes to us, still count it.
				this.sprite.getCollisions(this._heap.collisions);
				if (this._heap.collisions.length>0){
					//this._heap.spriteMoveRes = {
					//	collisions: this._heap.collisions,
					//	flags: DEFINE_SPRITE_MOVE_RESULT_FLAGS.COLLIDING_S
					//};
					this._heap.spriteMoveRes.init(DEFINE_SPRITE_MOVE_RESULT_FLAGS.COLLIDING_S, null, null, null, this._heap.collisions);
				}

				// hold for ~2 seconds
				if (this.state_timer>=this.hold_time){
					this.state="return";
					this.state_timer=0;
				}
			break;
			case "return":
				// return to host, if we have one and it's still active
				if (this.host_obj!=null && this.host_obj.manager!=null){
					this._heap.hostX = this.host_obj.sprite.x + ((this.host_obj.sprite.box_left + this.host_obj.sprite.box_right)>>1);
					this._heap.hostY = this.host_obj.sprite.y + ((this.host_obj.sprite.box_top + this.host_obj.sprite.box_bottom)>>1);
					this._heap.selfX = this.sprite.x + ((this.sprite.box_left + this.sprite.box_right)>>1);
					this._heap.selfY = this.sprite.y + ((this.sprite.box_top + this.sprite.box_bottom)>>1);

					this._heap.dx = this._heap.hostX - this._heap.selfX;
					this._heap.dy = this._heap.hostY - this._heap.selfY;
					if (this._heap.dx>0) this._heap.dx = Math.max(1,this._heap.dx>>3);
					else if (this._heap.dx<0) this._heap.dx = Math.min(-1,this._heap.dx>>3);
					if (this._heap.dy>0) this._heap.dy = Math.max(1,this._heap.dy>>3);
					else if (this._heap.dy<0) this._heap.dy = Math.min(-1,this._heap.dy>>3);

					this.sprite.move(this._heap.dx,this._heap.dy,  this._heap.spriteMoveRes);
				}
				// if not, dissipate (at least until we get evil and implement player-seeking)
				else{
					this.dissipate();
				}

			break;
			case "dissipate":
				// if we're dissipated, remove ourself
				if (this.dissipated){
					this.sprite.map_room.removeSprite(this.sprite);
					this.manager.remove(this);
					if (this.host_obj!=null){
						this.host_obj.removeSmoke(this);
						this.host_obj=null;
					}
				}
			break;
		}

		if (this._heap.spriteMoveRes!=null && this._heap.spriteMoveRes.flags){
			this._heap.absorbed=false;
			for (this._heap.i=0; !this._heap.absorbed && (this._heap.spriteMoveRes.flags & DEFINE_SPRITE_MOVE_RESULT_FLAGS.COLLIDING_S) && this._heap.i<this._heap.spriteMoveRes.collisions.length; this._heap.i++){
				if (this.host_obj && this._heap.spriteMoveRes.collisions[this._heap.i] == this.host_obj.sprite){
					this._heap.spriteMoveRes.collisions[this._heap.i].game_object.infect();
					this._heap.spriteMoveRes.collisions[this._heap.i].game_object.sfx = new Chiptune("FX_infect",SDS.sfxchip);
					this._heap.spriteMoveRes.collisions[this._heap.i].game_object.sfx.play(false);
					this.sprite.map_room.removeSprite(this.sprite);
					this.manager.remove(this);
					if (this.host_obj!=null){
						this.host_obj.removeSmoke(this);
						//this.host_obj=null;
						this._heap.absorbed=true;
					}
				}
			}
			for (this._heap.i=0; !this._heap.absorbed && (this._heap.spriteMoveRes.flags & DEFINE_SPRITE_MOVE_RESULT_EJECTED_S) && this._heap.i<this._heap.spriteMoveRes.ejections.length; this._heap.i++){
				if (this.host_obj && this._heap.spriteMoveRes.ejections[this._heap.i] == this.host_obj.sprite){
					this._heap.spriteMoveRes.ejections[this._heap.i].game_object.infect();
					this._heap.spriteMoveRes.ejections[this._heap.i].game_object.sfx = new Chiptune("FX_infect",SDS.sfxchip);
					this._heap.spriteMoveRes.ejections[this._heap.i].game_object.sfx.play(false);
					this.sprite.map_room.removeSprite(this.sprite);
					this.manager.remove(this);
					if (this.host_obj!=null){
						this.host_obj.removeSmoke(this);
						//this.host_obj=null;
						this._heap.absorbed=true;
					}
				}
			}
		}

		this.state_timer++;
		this.frame_timer++;

		this._heap.frame=0;
		if (this.state=="launch"){
			this._heap.frame = this.frame_timer>>2;
			this._heap.frame = Math.min(this._heap.frame,this.launch_frames.length-1);
			this.sprite.frame = this.launch_frames[this._heap.frame];
		}
		else if (this.state=="dissipate"){
			this._heap.frame = this.frame_timer>>1;
			if (this._heap.frame < this.dissipate_frames.length){
				this.sprite.frame = this.dissipate_frames[this._heap.frame];
			}
			else{
				this.dissipated=true;
			}
		}
		else{
			this._heap.frame = this.frame_timer>>2;
			if (this._heap.frame>=this.idle_frames.length){
				this.frame_timer=0;
				this._heap.frame=0;
			}
			this.sprite.frame = this.idle_frames[this._heap.frame];
		}
	};
