"use strict";

var EN_HappyShadow = function(){
	this.sprite = new Sprite(EN_HappyShadow.spriteSheet16,"HappyShadow");
	this.sprite.game_object = this; // no longer a generic GO
	this.sprite.frame = 1;

	this.face = new Sprite(EN_HappyShadow.spriteSheet32,"HappyShadowFace");
	this.face.game_object = this; // no longer a generic GO
	this.face.visible = false;
	this.face.collision_flags = 0;
	this.face.setBoundingBox(8,8,23,23);
	
	this.blobs = [];
	this._heap.b = 0;
	for (this._heap.b=0; this._heap.b<8; ++this._heap.b){
		this.blobs.push(new Sprite(EN_HappyShadow.spriteSheet8,"HappyShadowBlob"));
		this.blobs[this._heap.b].setBoundingBox(0,0,7,7);
		this.blobs[this._heap.b].collision_flags = 0;
		this.blobs[this._heap.b].game_object = this;
	}

	this._basicInit(EN_HappyShadow.params);

	//-----

	this.sprite.collision_flags |= 0;

	this.dx = 0;
	this.dy = 0;

	this.moveRes = new SpriteMoveResult();

	this.behavior = EN_HappyShadow.behaviors.IDLE;
	
	this.meli = null;
	this.meliFind=false; // she probably won't be in the map when we init; hopefully when we update

	this.frame_timer = 0;

	this.targetx = this.sprite.x;
	this.targety = this.sprite.y;
	this.hold_target = 0;

	this.phase = 0; // tricky enemy clears its collision on inflict so it CAN come back and double-jeopardy
};
EN_HappyShadow.spriteImg = SDS_Load_Image("art/sheets/sprite/happyshadow.png");
EN_HappyShadow.spriteSheet32 = new TileSheet(5, 5, 2, 0, EN_HappyShadow.spriteImg);
EN_HappyShadow.spriteSheet16 = new TileSheet(4, 4, 3, 1, EN_HappyShadow.spriteImg);
EN_HappyShadow.spriteSheet8 = new TileSheet(3, 3, 4, 2, EN_HappyShadow.spriteImg);
EN_HappyShadow.params = {
	name: "HappyShadow",
	box: [0,0,15,15], // left, top, right, bottom
	max_step: 2,
	hp: 1,
	infection: 8,
};
EN_HappyShadow.behaviors = {
		IDLE: 0, // do nothing but casual evasion
		PRIME: 1, // reveal
		HUNT: 2 // home on player
	};

// 0 1 2
// 7   3
// 6 5 4
EN_HappyShadow.blobX = [
	[-1,-1,-2,-2],
	[4,4,4,4],
	[9,9,10,10],
	[11,11,11,12],
	[9,9,10,10],
	[4,4,4,4],
	[-1,-1,-2,-2],
	[-3,-3,-3,-4],
];
EN_HappyShadow.blobY = [
	[-1,-1,-2,-2],
	[-3,-3,-3,-4],
	[-1,-1,-2,-2],
	[4,4,4,4],
	[9,9,10,10],
	[11,11,11,12],
	[9,9,10,10],
	[4,4,4,4],
];

EN_HappyShadow.prototype = new GO_Enemy();
	EN_HappyShadow.prototype.addToRoom = function(mapRoom){
		for (this._heap.b=0; this._heap.b<8; ++this._heap.b){
			mapRoom.addSprite(this.blobs[this._heap.b]);
		}
		mapRoom.addSprite(this.sprite);
		mapRoom.addSprite(this.face);
		this.face.x = this.sprite.x-8;
		this.face.y = this.sprite.y-8;
		
		this.updatePositions(0);
	}
	EN_HappyShadow.prototype.clearFromRoom = function(mapRoom){
		mapRoom.removeSprite(this.sprite);
		mapRoom.removeSprite(this.face);
		for (this._heap.b=0; this._heap.b<8; ++this._heap.b){
			mapRoom.removeSprite(this.blobs[this._heap.b]);
		}
	}
	EN_HappyShadow.prototype.updatePositions = function(frame){
		this.face.x = this.sprite.x-8;
		this.face.y = this.sprite.y-8;
		
		this._heap.b = 0;
		for (this._heap.b=0; this._heap.b<8; ++this._heap.b){
			this.blobs[this._heap.b].x = this.sprite.x+EN_HappyShadow.blobX[this._heap.b][frame];
			this.blobs[this._heap.b].y = this.sprite.y+EN_HappyShadow.blobY[this._heap.b][frame];
		}
	}
	EN_HappyShadow.prototype.stageEvade = function(){
		if (this.meli != null && this.meli.kicking){
			this._heap.dist = (this.meli.sprite.y + this.meli.sprite.center.y) - (this.sprite.y + this.sprite.center.y);
			if (this._heap.dist>=0 && this._heap.dist < 12){ // 16 would dodge every threat; 12 gives a couple px to land a glancing blow 
				this.targety = this.sprite.y - 16 + this._heap.dist;
				this.hold_target = 4; // kicking should hold for more than 1 frame, but jic, give time to ramp accel
			}
			else if (this._heap.dist<0 && this._heap.dist > -12){ 
				this.targety = this.sprite.y + 16 + this._heap.dist;
				this.hold_target = 4;
			}
		}
	}

	EN_HappyShadow.prototype.ai = function(){
		if (!this.meli && !this.meliFind){
			this.meli = this.manager.getNamedObject("Meli");
			this.meliFind = true;
		}

		// stay phased until meli can receive hits again
		// so we don't get caught in the old damage sources list
		if (this.phase){
			--this.phase;
			if (this.phase<0) this.phase = 0;
		}
		if (this.phase || (this.meli && (this.meli.hurt_timer || this.meli.iframes))){
			this.interactions &= ~DEFINE_GAMEOBJECT_INTERACTIONS.INFLICT;
		}
		else{
			this.interactions |= DEFINE_GAMEOBJECT_INTERACTIONS.INFLICT;
		}	

		if (this.hold_target){
			--this.hold_target;
			if (this.hold_target<0) this.hold_target = 0;
		}
		else{
			this.targetx = this.sprite.x;
			this.targety = this.sprite.y;
		}
		
		switch (this.behavior){
			case EN_HappyShadow.behaviors.IDLE:
				if (!this.hold_target) this.stageEvade();
			break;
			case EN_HappyShadow.behaviors.PRIME:
				if (!this.hold_target) this.stageEvade();
			break;
			case EN_HappyShadow.behaviors.HUNT:
				if (this.infection>0 && this.meli!=null){
					this.targetx = this.meli.sprite.x + this.meli.sprite.center.x - this.sprite.center.x;
					this.targety = this.meli.sprite.y + this.meli.sprite.box_top - this.sprite.center.y;
					this.hold_target = 0;
				}
			break;
		}

		
		if (this.targetx < this.sprite.x) --this.dx;
		else if (this.targetx > this.sprite.x) ++this.dx;
		else if (this.dx!=0) this.dx += (this.dx>0) ? -1 : 1;
		if (this.targety < this.sprite.y) --this.dy;
		else if (this.targety > this.sprite.y) ++this.dy;
		else if (this.dy!=0) this.dy += (this.dy>0) ? -1 : 1;
		this.dx = Math.max(-3,Math.min(this.dx,3));
		this.dy = Math.max(-3,Math.min(this.dy,3));

		this.sprite.move(this.dx,this.dy,this.moveRes);

		if (this.moveRes.flags & DEFINE_SPRITE_MOVE_RESULT_EJECTED_H){
			this.dx = -this.dx;
		}
		if (this.moveRes.flags & DEFINE_SPRITE_MOVE_RESULT_EJECTED_V){
			this.dy = -this.dy;
		}

		switch (this.behavior){
			case EN_HappyShadow.behaviors.IDLE:
				++this.frame_timer;
				this.frame_timer &= 31;
				this._heap.odd = (this.frame_timer&16) ? 1 : 0;

				this._heap.frame = ((this.frame_timer>>1)&7);
				if (this._heap.frame>3){
					this._heap.frame = 7-this._heap.frame;
				}
				this.updatePositions(this._heap.frame);
				this._heap.frame += 32;
				for (this._heap.b=0; this._heap.b<8; ++this._heap.b){
					this.blobs[this._heap.b].frame = this._heap.frame;
					this.blobs[this._heap.b].visible = !!((this._heap.b&1)^this._heap.odd);
				}
				this.sprite.frame = 1;
				this.face.visible = false;

				if (this.meli!=null && this.infection>0 && (this.frame_timer&15)==0){
					this._heap.dist = Math.abs(this.meli.sprite.x + this.meli.sprite.center.x - (this.sprite.x + this.sprite.center.x)) + 
						Math.abs(this.meli.sprite.y + this.meli.sprite.center.y - (this.sprite.y + this.sprite.center.y));
					if (this._heap.dist < 96){
						this.behavior = EN_HappyShadow.behaviors.PRIME;
						this.frame_timer = 0;
					}
				}
			break;
			case EN_HappyShadow.behaviors.PRIME:
				++this.frame_timer;
				this.frame_timer &= 31;

				this._heap.frame = ((this.frame_timer>>1)&7);
				if (this._heap.frame>3){
					this._heap.frame = 7-this._heap.frame;
				}
				this.updatePositions(this._heap.frame);
				this._heap.frame += 32;
				for (this._heap.b=0; this._heap.b<8; ++this._heap.b){
					this.blobs[this._heap.b].frame = this._heap.frame;
					this.blobs[this._heap.b].visible = true;
				}
				this.sprite.frame = 0;
				this.face.visible = true;
				this.face.frame = 1;

				if (this.meli!=null && this.infection>0 && (this.frame_timer&15)==0){
					this._heap.dist = Math.abs(this.meli.sprite.x + this.meli.sprite.center.x - (this.sprite.x + this.sprite.center.x)) + 
						Math.abs(this.meli.sprite.y + this.meli.sprite.center.y - (this.sprite.y + this.sprite.center.y));
					if (this._heap.dist < 64){
						this.behavior = EN_HappyShadow.behaviors.HUNT;
						this.frame_timer = 0;
					}
					if (this._heap.dist > 96){
						this.behavior = EN_HappyShadow.behaviors.IDLE;
						this.frame_timer = 0;
					}
				}
			break;
			case EN_HappyShadow.behaviors.HUNT:
				++this.frame_timer;
				this.frame_timer &= 15;

				this._heap.frame = (this.frame_timer&7);
				if (this._heap.frame>3){
					this._heap.frame = 7-this._heap.frame;
				}
				this.updatePositions(this._heap.frame);
				this._heap.frame += 32;
				for (this._heap.b=0; this._heap.b<8; ++this._heap.b){
					this.blobs[this._heap.b].frame = this._heap.frame;
					this.blobs[this._heap.b].visible = true;
				}
				this.sprite.frame = 0;
				this.face.visible = true;
				this.face.frame = 2 + ((this._heap.frame>>1)&1);

				if (this.meli!=null && this.infection>0 && (this.frame_timer&15)==0){
					this._heap.dist = Math.abs(this.meli.sprite.x + this.meli.sprite.center.x - (this.sprite.x + this.sprite.center.x)) + 
						Math.abs(this.meli.sprite.y + this.meli.sprite.center.y - (this.sprite.y + this.sprite.center.y));
					if (this._heap.dist > 96){
						this.behavior = EN_HappyShadow.behaviors.PRIME;
						this.frame_timer = 0;
					}
				}
			break;
		}

		//this.toggleInteractionsStd(); we need to force INFLICT and we die on 0 infection so DAMAGE is moot
	};
	EN_HappyShadow.prototype.damage = function(source,points){
		if (points>0){
			this.hp-=points;
			return (this.hp<=0);
		}
		else{
			//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=-2;
			this._heap.cough.launch_dir.y=-2;
			this._heap.cough.host_obj = this;

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

			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=2;
			this._heap.cough.launch_dir.y=-2;
			this._heap.cough.host_obj = this;

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

			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=2;
			this._heap.cough.launch_dir.y=2;
			this._heap.cough.host_obj = this;

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

			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=-2;
			this._heap.cough.launch_dir.y=2;
			this._heap.cough.host_obj = this;

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

			this._heap.cough = null;

			this.infection-=2; // yup.  spawn 4 smokes, but only drop infection by 2.  Will get stronger on reabsorb.  Shouldn't be encountering these without killwave anyway.
			if (this.infection<=0) this.hp=0;
			return (this.hp<=0); // shadow doesn't exist without infection
		}
	};
	//EN_HappyShadow.prototype._inflictVal = {hp:0, chi:-1};
	EN_HappyShadow.prototype.inflict = function(){
		//return this._inflictVal;
		this.phase = 2; // kill BB so we can re-inflict later
		return GLOBAL_DIARY.chi > 0 ?
			{
				hp:0,
				chi: GLOBAL_DIARY.hasBlessing ? -4 : 4 // always suck energy
			} :
			{
				hp:1,
				chi: 0 // always suck energy
			};
	};
	EN_HappyShadow.prototype.drop = function(){
		this._heap.dropRand = Math.random();
		if (this._heap.dropRand<0.01){
			return new GO_HeartDrop(GO_HeartDrop.SIZE.BIG);
		}
		return null;
	};


