"use strict";
/* Don't be this guy */
var GO_Boss_Guy = function(){
	this.sprite= new Sprite(GO_Boss_Guy.spriteSheet,"BossGuy");
	this.sprite.collision_flags = 
		DEFINE_SPRITE_COLLISION_FLAGS.GROUND | 
		DEFINE_SPRITE_COLLISION_FLAGS.AIR |
		DEFINE_SPRITE_COLLISION_FLAGS.SPRITES_ACTIVE |
		DEFINE_SPRITE_COLLISION_FLAGS.SPRITES_PASSIVE;
	this.sprite.setBoundingBox(2,0,13,15);
	//this.sprite.constraints=constraints;
	this.sprite.max_step = 2;
	this.sprite.game_object = this; // no longer a generic GO

	this.hp = 10;
	this.infection = 1;
	this.smoke = [];

	this.controls = new Controls(); // just to init

	this.leftward_move_water = [0,-1,-1];
	this.rightward_move_water = [0,1,1];
	this.horizontal_move_index=0;

	this.upward_move_water = [0,-1,-1];
	this.downward_move_water = [0,1,1];
	this.vertical_move_index = 0;

	this.ANIM_STATES = {
		"bob" : 0,
		"swim" : 1,
		"rocket" : 2,
		"fire" : 3,
		"dead" : 4,
	};
	this.anim_state = this.ANIM_STATES.bob;

	this.CONTROL_STATES = {
		"prefight" : 0,
		"flee" : 1,
		"rocket" : 2,
		"aim" : 3,
		"fire" : 4,
		"postfight" : 5
	};
	this.control_state = this.CONTROL_STATES.prefight;
	this.control_timer = 0;

	this.anim_frames = [
		[0,0,1,1], //"bob" : 
		[0,1,0,2], //"swim" : 
		[8,9], //"rocket" : 
		[12,13,14], //"throw" 
		[11], //"dead"
	];
	this.frame_timer=0;

	this.direction = 1; // +/-1 for facing
	this.rock=null;

	this.meli = null;
	this.meliFind=false; // she probably won't be in the map when we init; hopefully when we update
};
GO_Boss_Guy.spriteImg = SDS_Load_Image("art/sheets/sprite/guy_infected.png");
GO_Boss_Guy.spriteSheet = new TileSheet(4, 4, 3, 2, GO_Boss_Guy.spriteImg);

GO_Boss_Guy.prototype = new GameObject(
	new Sprite(
		GO_Boss_Guy.spriteSheet,
		"BossGuy"
	),
	"BossGuy"
	);

	GO_Boss_Guy.prototype.interactions = 
		DEFINE_GAMEOBJECT_INTERACTIONS.CONTROL |
		DEFINE_GAMEOBJECT_INTERACTIONS.CHECK;

	GO_Boss_Guy.prototype.checkEvent = function(sourceGO){
		if (sourceGO && sourceGO.sprite && this.control_state!=this.CONTROL_STATES.postfight) this.direction = (sourceGO.sprite.x<this.sprite.x) ? -1 : 1;
		
		//var retval=null;
		this._heap.retval=null;

		if (this.control_state==this.CONTROL_STATES.prefight) this._heap.retval = "Guy_bossfight_1";
		if (this.control_state==this.CONTROL_STATES.postfight) this._heap.retval = "Guy_bossfight_2";
		
		return this._heap.retval;
	};

	GO_Boss_Guy.prototype.startFight = function(){
		this.control_state = this.CONTROL_STATES.flee;
		this.sprite.collision_flags = 
			DEFINE_SPRITE_COLLISION_FLAGS.GROUND | 
			DEFINE_SPRITE_COLLISION_FLAGS.AIR |
			DEFINE_SPRITE_COLLISION_FLAGS.SPRITES_PASSIVE;
		this.interactions = 
			DEFINE_GAMEOBJECT_INTERACTIONS.CONTROL |
			DEFINE_GAMEOBJECT_INTERACTIONS.DAMAGE |
			DEFINE_GAMEOBJECT_INTERACTIONS.INFLICT;
	};

	GO_Boss_Guy.prototype.endFight = function(){
		SDS.bgmName = null;
		SDS.bgm.stop();
		//SDS.bgm = new Chiptune(SDS.bgmName,SDS.bgmchip);
		//SDS.bgm.play(true);
		
		this.control_state = this.CONTROL_STATES.postfight;
		this.sprite.collision_flags = 
			DEFINE_SPRITE_COLLISION_FLAGS.GROUND | 
			DEFINE_SPRITE_COLLISION_FLAGS.AIR |
			DEFINE_SPRITE_COLLISION_FLAGS.SPRITES_ACTIVE |
			DEFINE_SPRITE_COLLISION_FLAGS.SPRITES_PASSIVE;
		this.interactions = 
			DEFINE_GAMEOBJECT_INTERACTIONS.CONTROL |
			DEFINE_GAMEOBJECT_INTERACTIONS.CHECK;
	};

	GO_Boss_Guy.prototype.cleanupFight = function(){
		//var soul = new GO_Soul("GUY");
		this._heap.soul = new GO_Soul("GUY");
		this._heap.soul.spawnOnSprite(this.sprite,this.manager);
		this._heap.soul = null;

		//var poof = new GO_Poof();
		this._heap.poof = new GO_Poof();
		this._heap.poof.spawnOnSprite(this.sprite,this.manager);
		this._heap.poof = null;

		this.sprite.map_room.removeSprite(this.sprite);
		this.manager._remove(this); // outside the update loop, so do it immediately
	};

	// Enemy-style support routines
	GO_Boss_Guy.prototype.damage = function(source,points){
		if (points>0){
			this.hp-=points;
			

			//var cough = new GO_Smoke();
			this._heap.cough = new GO_Smoke();
			this._heap.cough.sprite.x = this.sprite.x;
			this._heap.cough.sprite.y = this.sprite.y;
			//this._heap.cough.launch_dir = {x:this.direction, y:0};
			this._heap.cough.launch_dir.x=0;
			this._heap.cough.launch_dir.y=-1;
			this._heap.cough.host_obj = this;

			this.sprite.map_room.addSprite(this._heap.cough.sprite);
			this.manager.add(this._heap.cough);
			this.smoke.push(this._heap.cough);

			this._heap.cough = null;

			//this.infection--;
			return (this.hp<=0);
		}
		else{
			return false;
		}
	};
	GO_Boss_Guy.prototype._inflictVal = {hp:1, chi:0};
	GO_Boss_Guy.prototype.inflict = function(){
		return this._inflictVal;
	};

	GO_Boss_Guy.prototype.removeSmoke = function(smoke){
		var index = this.smoke.indexOf(smoke);
		if (index!=-1){
			this.smoke.splice(index,1);
			smoke.host_obj=null;
		}
	};
	GO_Boss_Guy.prototype.infect = function(){
		//this.infection++;
		this.hp+=2;
	};

	GO_Boss_Guy.prototype.aiControl = function(){
		switch (this.control_state){
			case this.CONTROL_STATES.flee:

				if (this.meli){
					if (this.meli.sprite.x>this.sprite.x){
						this.controls.unpress(this.controls,"right");
						this.controls.press(this.controls,"left");
					}
					else if (this.meli.sprite.x<this.sprite.x){
						this.controls.unpress(this.controls,"left");
						this.controls.press(this.controls,"right");
					}
					else{
						this.controls.unpress(this.controls,"right");
						this.controls.unpress(this.controls,"left");
					}

					if (this.meli.sprite.y>this.sprite.y){
						this.controls.unpress(this.controls,"down");
						this.controls.press(this.controls,"up");
					}
					else if (this.meli.sprite.y<this.sprite.y){
						this.controls.unpress(this.controls,"up");
						this.controls.press(this.controls,"down");
					}
					else{
						this.controls.unpress(this.controls,"down");
						this.controls.unpress(this.controls,"up");
					}
				}

				this.control_timer++;
				if (this.control_timer >= 120){
					this.control_timer = 0;
					this.controls.unpress(this.controls,"right");
					this.controls.unpress(this.controls,"left");
					this.controls.unpress(this.controls,"down");
					this.controls.unpress(this.controls,"up");

					this.controls.press(this.controls,"A");

					this.control_state = this.CONTROL_STATES.rocket;
				}
			break;
			case this.CONTROL_STATES.rocket:
				if (this.rock!=null){
					this.control_timer = 0;
					this.controls.unpress(this.controls,"A");
					this.control_state = this.CONTROL_STATES.aim;
				}
			break;
			case this.CONTROL_STATES.aim:
				if (this.meli){
					if (this.meli.sprite.x<this.sprite.x){
						this.controls.unpress(this.controls,"right");
						this.controls.press(this.controls,"left");
					}
					else if (this.meli.sprite.x>this.sprite.x){
						this.controls.unpress(this.controls,"left");
						this.controls.press(this.controls,"right");
					}
					else{
						this.controls.unpress(this.controls,"right");
						this.controls.unpress(this.controls,"left");
					}

					if (this.meli.sprite.y<this.sprite.y){
						this.controls.unpress(this.controls,"down");
						this.controls.press(this.controls,"up");
					}
					else if (this.meli.sprite.y>this.sprite.y){
						this.controls.unpress(this.controls,"up");
						this.controls.press(this.controls,"down");
					}
					else{
						this.controls.unpress(this.controls,"down");
						this.controls.unpress(this.controls,"up");
					}
				}

				this.control_timer++;
				if (this.control_timer >= 120){
					this.control_timer = 0;
					this.controls.unpress(this.controls,"right");
					this.controls.unpress(this.controls,"left");
					this.controls.unpress(this.controls,"down");
					this.controls.unpress(this.controls,"up");

					this.controls.press(this.controls,"B");

					this.control_state = this.CONTROL_STATES.fire;
				}
			break;
			case this.CONTROL_STATES.fire:
				this.control_timer++;
				if (this.control_timer >= 30){
					this.control_timer = 0;

					this.controls.unpress(this.controls,"B");

					this.control_state = this.CONTROL_STATES.flee;
				}
			break;
			case this.CONTROL_STATES.postfight:
				this.controls.unpress(this.controls,"right");
				this.controls.unpress(this.controls,"left");
				this.controls.unpress(this.controls,"down");
				this.controls.unpress(this.controls,"up");
				this.controls.unpress(this.controls,"A");
				this.controls.unpress(this.controls,"B");

				this.control_timer++;
				this.control_timer&=31;
				if (!(this.control_timer&7)){
					if (this.control_timer&16){
						this.controls.press(this.controls,"up");
					}
					else{
						this.controls.press(this.controls,"down");
					}
				}
			break;
		}
	};

	GO_Boss_Guy.prototype.Update = function(){
		// peaceful mob style target lookup
		if (!this.meli && !this.meliFind){
			this.meli = this.manager.getNamedObject("Meli");
			this.meliFind = true;
		}
		//if (this.meli){
		//	this.direction = (this.meli.sprite.x>this.sprite.x) ? 1 : -1;
		//}

		this.aiControl();

		// generic mob style control update
		/*var dx = 0;
		var dy = 0;
		var old_xs = [];
		var new_xs = [];
		var dxs = [];
		var old_ys = [];
		var new_ys = [];
		var dys = [];
		var spriteMoveRes = null;

		var leftMoveArr = null;
		var rightMoveArr = null;
		var upMoveArr = null;
		var downMoveArr = null;

		var oldAnimState = this.anim_state;

		var i=0;*/
		this._heap.dx = 0;
		this._heap.dy = 0;
		//var old_xs = [];
		//var new_xs = [];
		//var dxs = [];
		//var old_ys = [];
		//var new_ys = [];
		//var dys = [];

		this._heap.leftMoveArr = null;
		this._heap.rightMoveArr = null;
		this._heap.upMoveArr = null;
		this._heap.downMoveArr = null;

		this._heap.oldAnimState = this.anim_state;

		this._heap.i=0;

		
		this.anim_state = this.ANIM_STATES.bob;

		// rocket to ceiling and grab a boulder
		if (this.controls.held.A && this.rock==null){
			this.anim_state = this.ANIM_STATES.rocket;

			if (!(this.controls.pressed.A) || (this.frame_timer>>2 > 0)){
				this.sprite.move(0,-4,  this._heap.spriteMoveRes);

				if (this._heap.spriteMoveRes.flags & DEFINE_SPRITE_MOVE_RESULT_EJECTED_V){
					if (this.sfx) this.sfx.stop();
					this.sfx = new Chiptune("FX_fallcrash",SDS.sfxchip);
					this.sfx.play(false);
					
					this.rock = new GO_GuyRock();
					this.rock.cachedUpdate = this.rock.Update;
					this.rock.Update = noop;

					this.sprite.map_room.addSprite(this.rock.sprite);
					this.manager.add(this.rock);
				}
			}

		}
		// throw boulder
		else if (this.controls.held.B){
			this.anim_state = this.ANIM_STATES.fire;

			if (this.rock!=null){
				if (this.meli){
					this.direction = (this.meli.sprite.x>this.sprite.x) ? 1 : -1;

					// cheat a bit with straight trig, since it's more convenient
					// and will achieve an identical result to an oldschool LUT
					this._heap.targetAngle = Math.atan2(this.meli.sprite.y-this.rock.sprite.y, this.meli.sprite.x-this.rock.sprite.x);
					this.rock.dx = Math.round(16*Math.cos(this._heap.targetAngle));
					this.rock.dy = Math.round(16*Math.sin(this._heap.targetAngle));
				}
				if (this.rock.cachedUpdate){
					this.rock.Update = this.rock.cachedUpdate;
					delete this.rock.cachedUpdate;
				}
				this.rock.sprite.collision_flags = 
					DEFINE_SPRITE_COLLISION_FLAGS.GROUND | 
					DEFINE_SPRITE_COLLISION_FLAGS.SPRITES_ACTIVE |
					DEFINE_SPRITE_COLLISION_FLAGS.SPRITES_PASSIVE;
				this.rock=null;
			}
		}
		else{

			this.NPCSwim(this.anim_state);
		}

		if (this.rock!=null){
			this._heap.newHeldX = (this.direction>0) ? (this.sprite.x+1) : (this.sprite.x+14);
			this._heap.newHeldX -= (this.direction>0) ? this.rock.hoistpoint[0].x : this.rock.hoistpoint[1].x;
			this._heap.newHeldY = (this.sprite.y+1);
			this._heap.newHeldY -= (this.direction>0) ? this.rock.hoistpoint[0].y : this.rock.hoistpoint[1].y;
			this.rock.sprite.x = this._heap.newHeldX;
			this.rock.sprite.y = this._heap.newHeldY;
		}

		if (this.control_state==this.CONTROL_STATES.postfight) this.anim_state = this.ANIM_STATES.dead;
		

		if (this._heap.oldAnimState != this.anim_state){
			this.frame_timer=0;
		}
		this.frame_timer++;
		this._heap.aniFrame = (this.frame_timer>>2);
		if (this.anim_state==this.ANIM_STATES.swim || this.anim_state==this.ANIM_STATES.bob){
			this._heap.aniFrame = this._heap.aniFrame% this.anim_frames[this.anim_state].length;
		}
		else{
			this._heap.aniFrame = Math.min(this._heap.aniFrame,this.anim_frames[this.anim_state].length-1);
		}

		this.sprite.frame = this.anim_frames[this.anim_state][this._heap.aniFrame];

		//this.sprite.frame = this.sprite.frame & 7;
		if (this.rock!=null) this.sprite.frame+=4;
		if (this.direction<0) this.sprite.frame+=16;



		// Enemy-style check HP and destroy
		// TODO: instead, throw an event
		if (this.hp<=0 && this.control_state!=this.CONTROL_STATES.postfight){
			//var poof;
			if (this.rock!=null){
				this._heap.poof = new GO_Poof();
				this._heap.poof.spawnOnSprite(this.rock.sprite,this.manager);
				this._heap.poof = null;

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

			while (this.smoke.length>0){
				// var s;
				//this._heap.s = this.smoke.pop();
				//if (this._heap.s.state!="dissipate"){
				//	this._heap.s.state="dissipate";
				//	this._heap.s.state_timer = 0;
				//	this._heap.s.frame_timer = 0;
				//	this._heap.s.interactions = 0;
				//}
				if (this.smoke[0].state!="dissipate"){
					this.smoke[0].state="dissipate";
					this.smoke[0].state_timer = 0;
					this.smoke[0].frame_timer = 0;
					this.smoke[0].interactions = 0;
				}
				this.smoke.shift();
			}

			// yeah, it would be better to instance-track, but since they destroy themselves
			// and I'm lazy and this is js, meh.
			// var rock;
			this._heap.rock = this.manager.getNamedObject("GuyBoulder");
			while (this._heap.rock ){
				// var poof;
				this._heap.poof = new GO_Poof();
				this._heap.poof.spawnOnSprite(this._heap.rock.sprite,this.manager);
				this._heap.poof = null;

				this._heap.rock.sprite.map_room.removeSprite(this._heap.rock.sprite);
				this._heap.rock.manager.remove(this._heap.rock);
				this._heap.rock = this.manager.getNamedObject("GuyBoulder");
			}

			this.endFight();
		}
	};
	// does the basic make-dangerous-iff-infected check.
	// some enemies may want to be dangerous even when uninfected,
	// so let individual AIs handle the call.
	GO_Boss_Guy.prototype.toggleInteractionsStd = function(){
		if (this.infection>0){
			this.interactions |= 
				DEFINE_GAMEOBJECT_INTERACTIONS.DAMAGE |
				DEFINE_GAMEOBJECT_INTERACTIONS.INFLICT;
		}
		else{
			this.interactions &=
				~DEFINE_GAMEOBJECT_INTERACTIONS.DAMAGE &
				~DEFINE_GAMEOBJECT_INTERACTIONS.INFLICT;
		}
	};

