"use strict";

var EN_Spider = function(){
	this.sprite = new Sprite(EN_Spider.spriteSheet,"Spider");
	this.sprite.game_object = this; // no longer a generic GO

	this._basicInit(EN_Spider.params);

	//-----

	this.sprite.collision_flags |= DEFINE_SPRITE_COLLISION_FLAGS.GROUND |
								DEFINE_SPRITE_COLLISION_FLAGS.SPRITES_ACTIVE; // to walk on nuts

	this.controls = new Controls(); // ground-runner; easier to just patch in standard controls


	this.direction = 1;

	this.grounded = false;
	this.in_water_cache = false;
	this.horizontal_move_index = 0;
	this.jump_index = 0;
	this.fall_index = 0;

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

	this.threadX = -1;
	this.threadY = -1;
	this.swing = 0;
	this.threadSprite = new Sprite(EN_Spider.spriteSheet,"Spider_thread");
	this.threadSprite.game_object = this; // no longer a generic GO
	this.threadSprite.frame = 3;
	this.bullet_timer = 128; // countdown to burst in last second

	this.anim_state = this.ANIM_STATES.hang;
	this.frame_timer=0;

	this.behavior_state = this.BEHAVIOR_STATES.hang;
	this.behavior_timer = 0;
	this.leftward_move_land = this.leftward_walk_land;
	this.rightward_move_land = this.rightward_walk_land;

	this.touching = []; // for flycatching
};
EN_Spider.spriteImg = SDS_Load_Image("art/sheets/sprite/spider.png");
EN_Spider.spriteSheet = new TileSheet(4, 4, 2, 2, EN_Spider.spriteImg);
EN_Spider.params = {
	name: "Spider",
	box: [0,5,14,15], // left, top, right, bottom
	max_step: 2,
	hp: 2,
	infection: 2,
};

EN_Spider.prototype = new GO_Enemy();

	EN_Spider.prototype.interactions = GO_Enemy.prototype.interactions |
			DEFINE_GAMEOBJECT_INTERACTIONS.CONTROL;

	// NPC walk controls
	EN_Spider.prototype.leftward_walk_land = [0,-1];
	EN_Spider.prototype.rightward_walk_land = [0,1];
	EN_Spider.prototype.leftward_move_water = [0,-1];
	EN_Spider.prototype.rightward_move_water = [0,1];
	EN_Spider.prototype.jump_rise_air = [ //27px = 1.75 blocks
		-4,-4,-4,-4,
		-3,-3, 
		-2,-2,
		-1,
		0, 0];
	EN_Spider.prototype.fall_air = [ 
		1, 
		2, 2, 2, 
		3, 3, 3, 
		4, 4, 4, 4, 4, 4, 
		5, 5, 5, 5, 5, 5,
		6, 6, 6, 6, 6, 6,
		7, 7, 7, 7, 7, 7, 
		8];
	EN_Spider.prototype.jump_rise_water = [ //8px = .5 blocks
		-2, -2, -2, 
		-1, -1, 
		0]; // maybe a bird; not a duck.
	EN_Spider.prototype.fall_water = [ 
		-1]; // naturally buoyant; "fall" towards surface

	EN_Spider.prototype.ANIM_STATES = {
		"stand" : 0,
		"walk" : 1,
		"jump" : 2,
		"fall" : 3,
		"hang" : 4
	};
	EN_Spider.prototype.anim_frames = [
		[1], //"stand" : 
		[1,2], //"walk" : 
		[1], //"jump" : 
		[1], //"fall" :
		[0] // "hang" :
	];

	EN_Spider.prototype.BEHAVIOR_STATES = {
		"hang" : 0,
		"meander" : 1,
		"seek" : 2
	};

	EN_Spider.prototype.ai = function(){
		if (!this.meli && !this.meliFind){
			this.meli = this.manager.getNamedObject("Meli");
			this.meliFind = true;
		}
		if (this.threadSprite.map_room==null && this.sprite.map_room!=null && this.hp>0){
			this.sprite.map_room.addSprite(this.threadSprite);
		}

		this._heap.oldAnimState=this.anim_state;

		++this.behavior_timer;
		switch (this.behavior_state){
			case this.BEHAVIOR_STATES.hang:
				if (this.threadY<0){
					this.threadX = this.sprite.x + 7;
					// search level for nearest above solid as threadY
					this.threadY = this.sprite.y - this.sprite.map_room.findVertically(DEFINE_MAP_TERRAIN_TYPES.GROUND,this.threadX,this.sprite.y,-1,128);
				}

				if (this.meli){
					// if meli crosses the thread, fall into seek
					if ((this.meli.sprite.y+this.meli.sprite.box_bottom<this.sprite.y+this.sprite.box_top) && 
						(this.meli.sprite.y+this.meli.sprite.box_top>this.threadY) &&
						(this.meli.sprite.x+this.meli.sprite.box_left<=this.threadX) &&
						(this.meli.sprite.x+this.meli.sprite.box_right>=this.threadX)){
						this.behavior_state = (this.infection>0) ? this.BEHAVIOR_STATES.seek : this.BEHAVIOR_STATES.meander;
					}
				}

				// if hit, do swing behavior about thread x/y
				// add swing to x
				// add +/-1 to swing dependng on side of 0
				// if swing hit/crossed 0, nudge swing towards 0
				this._heap.oldOffCenter = this.sprite.x+7 - this.threadX;
				this.sprite.move(this.swing,0, this._heap.spriteMoveRes);
				this._heap.offCenter = this.sprite.x+7 - this.threadX;
				this.swing += (this._heap.offCenter>0) ? -1 : (this._heap.offCenter<0) ? 1 : 0;
				if ((this._heap.oldOffCenter<0 && this._heap.offCenter>=0) ||
					(this._heap.oldOffCenter>0 && this._heap.offCenter<=0)){
					this.swing += (this.swing>0) ? -1 : (this.swing<0) ? 1 : 0;
				}

				if (this.behavior_timer&1){
					if (this.behavior_timer<64 || this.behavior_timer>=256) this.sprite.move(0,-1,this._heap.spriteMoveRes);
					else if (this.behavior_timer>=96 && this.behavior_timer<224) this.sprite.move(0,1,this._heap.spriteMoveRes);
					if (this.behavior_timer>=320) this.behavior_timer=0;
				}

				if (this.infection>0){
					--this.bullet_timer;
					if (this.bullet_timer<32 && (this.bullet_timer&3)==0){
						// spit
						this._heap.spit = new GO_Bullet(0,2<<3);
						this._heap.spit.sprite.x = (this.bullet_timer&7)==0 ?
							this.sprite.x+3 :
							this.sprite.x+4;
						this._heap.spit.sprite.y = this.sprite.y+14;

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

						this._heap.spit = null;
					}
					if (this.bullet_timer==0) this.bullet_timer=128;
				}

			break;

			case this.BEHAVIOR_STATES.meander:
				// move/pause/repeat
				// if infected & seen; seek.

				this.controls.unpress(this.controls,"left");
				this.controls.unpress(this.controls,"right");

				if (this.grounded && this.behavior_timer<=60){
					this.leftward_move_land = this.leftward_walk_land;
					this.rightward_move_land = this.rightward_walk_land;
					this.controls.press(this.controls,this.direction<0 ? "left" : "right");
					this.controls.unpress(this.controls,this.direction<0 ? "right" : "left");
				}
				else if (this.behavior_timer>=90){
					this.behavior_timer=0;
				}

				if (this.infection>0){
					this._heap.seenMeli = this.meli && 
						(this.meli.sprite.y+this.meli.sprite.box_bottom>this.sprite.y+this.sprite.box_top) && 
						(this.meli.sprite.y+this.meli.sprite.box_top<this.sprite.y+this.sprite.box_bottom);
					this._heap.seenMeli &= this.meli &&
						((this.direction<0 && this.meli.sprite.x+this.meli.sprite.box_left < this.sprite.x+this.sprite.box_left) ||
						(this.direction>0 && this.meli.sprite.x+this.meli.sprite.box_right > this.sprite.x+this.sprite.box_right));	
				

					if (this._heap.seenMeli){
						this.behavior_timer=0;
						this.behavior_state = this.BEHAVIOR_STATES.seek;
					}
					else if (this.behavior_timer==0){
						this.direction *= -1;
					}
				}
			break;

			case this.BEHAVIOR_STATES.seek:
				// while seen, move towards
				// when not seen, meander

				this._heap.seenMeli = this.meli && 
					(this.meli.sprite.y+this.meli.sprite.box_bottom>this.sprite.y+this.sprite.box_top) && 
					(this.meli.sprite.y+this.meli.sprite.box_top<this.sprite.y+this.sprite.box_bottom);
				this._heap.seenMeli &= this.meli &&
					((this.direction<0 && this.meli.sprite.x+this.meli.sprite.box_left < this.sprite.x+this.sprite.box_left) ||
					(this.direction>0 && this.meli.sprite.x+this.meli.sprite.box_right > this.sprite.x+this.sprite.box_right));	

				if (!this._heap.seenMeli){
					this.behavior_timer=0;
					this.behavior_state = this.BEHAVIOR_STATES.meander;
				}
				else if (this.grounded){
					this.leftward_move_land = this.leftward_walk_land;
					this.rightward_move_land = this.rightward_walk_land;
					this.controls.press(this.controls,this.direction<0 ? "left" : "right");
					this.controls.unpress(this.controls,this.direction<0 ? "right" : "left");
				}
			break;
		}

		
		if (this.behavior_state !== this.BEHAVIOR_STATES.hang) this.NPCWalk();

		if (this._heap.spriteMoveRes.flags & DEFINE_SPRITE_MOVE_RESULT_FLAGS.EJECTED_H){
			this.direction *= -1;
			this.behavior_state=this.BEHAVIOR_STATES.meander;
			this._heap.spriteMoveRes.flags &= ~DEFINE_SPRITE_MOVE_RESULT_FLAGS.EJECTED_H; // because _heap is shared by all instances, and thus if another instance moves and we don't, we get its _moveRes :P
		}

		this.sprite.getCollisions(this.touching);
		for (this._heap.i = 0; this._heap.i<this.touching.length; ++this._heap.i){
			if (this.touching[this._heap.i].game_object instanceof EN_Mosquito){
				this.hp += this.touching[this._heap.i].game_object.hp;
				this.infection += this.touching[this._heap.i].game_object.infection;
				this.touching[this._heap.i].game_object.damage(this,this.touching[this._heap.i].game_object.hp);
			}
		}
		this.touching.length=0; // don't retain references
		

		this.toggleInteractionsStd();

		if (this._heap.oldAnimState != this.anim_state){
			this.frame_timer=0;
		}
		this.frame_timer++;
		this._heap.aniFrame = (this.frame_timer>>(this.infection ? 2 : 3)) % this.anim_frames[this.anim_state].length;

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

		this.sprite.frame = this.sprite.frame & 7;

		if (this.infection>0) this.sprite.frame+=8;
		if (this.direction<0) this.sprite.frame+=4;

		if (this.behavior_state==this.BEHAVIOR_STATES.hang){
			this.threadSprite.x = ((this.threadX-7)+this.sprite.x)>>1;
			this.threadSprite.y = ((this.sprite.y + this.threadY)>>1)-8-this.swing;
			this.threadSprite.visible = ((this.frame_timer&1) && (this.sprite.y - this.threadY > 16));
		}
		else{
			this.threadSprite.visible = false;
		}
	};
	EN_Spider.prototype.damage = function(source,points){
		
		
		// face away from attacker when hit
		if (source!=this){
			if (source.sprite.x + (source.sprite.box_left+source.sprite.box_right)>>1 < this.sprite.x + (this.sprite.box_left+this.sprite.box_right)>>1){
				this.direction = 1;
				this.swing = 4;
			}
			else{
				this.direction = -1;
				this.swing=-4;
			}
		}

		if (points>0){
			this.hp-=points;
		}
		else{
			this._heap.cough = new GO_Smoke();
			if (this.behavior_state !== this.BEHAVIOR_STATES.hang){ // already flipped, so smoke towards attacker
				this._heap.cough.sprite.x = this.sprite.x + ((this.direction>0) ? 8 : -8);
				this._heap.cough.sprite.y = this.sprite.y;
				this._heap.cough.launch_dir.x=((this.direction<0) ? 1 : -1);
				this._heap.cough.launch_dir.y=0;
			}
			else{
				this._heap.cough.sprite.x = this.sprite.x;
				this._heap.cough.sprite.y = this.sprite.y - 8;
				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._heap.cough = null;

			this.infection--;
		}

		if (this.behavior_state===this.BEHAVIOR_STATES.seek){
			this.behavior_timer=0;
			this.behavior_state=this.BEHAVIOR_STATES.meander;
		}

		// if we're going away, clean up what won't get auto-cleaned
		if (this.hp<=0 && this.threadSprite.map_room!=null){
			this.threadSprite.map_room.removeSprite(this.threadSprite);
		}

		return (this.hp<=0);
		
	};
	EN_Spider.prototype._inflictVal = {hp:1, chi:2};
	EN_Spider.prototype.inflict = function(){
		return this._inflictVal;
	};
	EN_Spider.prototype.drop = function(){
		this._heap.dropRand = Math.random();
		if (this._heap.dropRand<0.1){
			return new GO_HeartDrop(GO_HeartDrop.SIZE.BIG);
		}
		else if (this._heap.dropRand<0.4){
			return new GO_HeartDrop(GO_HeartDrop.SIZE.SMALL);
		}
		return null;
	};


