"use strict";

var GO_Wind = function(mapW, mapH){
	this.sprite = new Sprite(GO_Wind.spriteSheet,"Wind"); // so all instances have different sprites
	this.sprite.collision_flags = 0;
	this.sprite.setBoundingBox(0,0,6,6);
	this.sprite.game_object = this; // no longer a generic GO

	this.w = mapW;
	this.h = mapH;
	this.pw = mapW<<4;
	this.ph = mapH<<4;

	// aiming for a density of ~1 in every 4x4 tile box
	this.num_sprites = (mapW * mapH)>>4;
	this.num_sprites = this.num_sprites || 1;

	// now... how to distribute those sprites even-ish-ly
	// in a WxH box WITHOUT resorting to random()...
	// let's fix to height/4 rows of spawn points,
	// and see where spreading the sprites out uniformly
	// along them gets us...
	// authenticity would dictate using e.g. subtract-and-shift
	// soft-division; not going to write the algo just to avoid
	// using a floor'd / in a cosmetic capacity
	this.spawn_rows = mapH>>2;
	this.h_step = Math.floor(this.ph / this.spawn_rows);
	this.w_step = Math.floor(this.spawn_rows * this.pw / this.num_sprites);



	
	this.spawn_step = Math.floor(this.pw * this.ph / this.num_sprites);

	this.sprites = [];
	this.sprites[0] = this.sprite; // let's not waste this
	this.sprite_ages = [];
	this.sprite_ages[0] = 0;
	for (this._heap.i=1; this._heap.i<this.num_sprites; ++this._heap.i){
		this.sprites[this._heap.i] = new Sprite(GO_Wind.spriteSheet,"Wind"); // so all instances have different sprites
		this.sprites[this._heap.i].collision_flags = 0;
		this.sprites[this._heap.i].setBoundingBox(0,0,6,6);
		this.sprites[this._heap.i].game_object = this; // no longer a generic GO

		this.sprite_ages[this._heap.i] = (((this._heap.i&255)<<3)|((this._heap.i&255)>>5))^0xaa;//(this._heap.i&255);

		this.homePos(this.sprites[this._heap.i],this._heap.i);
		this.sprites[this._heap.i].x += this.sprite_ages[this._heap.i]>>2;
		this.sprites[this._heap.i].x %= this.pw;
		this.sprites[this._heap.i].y += this.sprite_ages[this._heap.i]>>2;
		this.sprites[this._heap.i].y %= this.ph;
	}

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

	this.active = true;
	this.direction = 0; // 0-7 clockwise from (1,0)
	this.intensity = 0; // 0-2 px/frame
	this.timer = 0;
};
GO_Wind.spriteImg = SDS_Load_Image("art/sheets/sprite/wind.png");
GO_Wind.spriteSheet = new TileSheet(3, 3, 3, 1, GO_Wind.spriteImg);

GO_Wind.prototype = new GameObject(
	new Sprite(
		GO_Wind.spriteSheet,
		"Wind"
	),
	"Wind"
	);

	GO_Wind.prototype.interactions = 0;

	GO_Wind.prototype.intensity_map = [
		[0,0,0,0],
		[1,0,1,0],
		[1,1,1,1]
	];

	GO_Wind.prototype.addToRoom = function(mapRoom){
		for (this._heap.i=0; this._heap.i<this.num_sprites; ++this._heap.i){
			mapRoom.addSprite(this.sprites[this._heap.i]);
		}
	}

	GO_Wind.prototype.homePos = function(sprite,idx){
		this._heap.spawn_raster = this.w_step * idx;
		sprite.x = this._heap.spawn_raster % this.pw;
		sprite.y = this.h_step * Math.floor(this._heap.spawn_raster / this.pw);
	}

	GO_Wind.prototype.Update = function(){
		if (!this.active){
			for (this._heap.i=0; this._heap.i<this.num_sprites; ++this._heap.i){
				this.sprites[this._heap.i].visible = false;
			}
			return;
		}
		
		if (!this.meli && !this.meliFind){
			this.meli = this.manager.getNamedObject("Meli");
			this.meliFind = true;
		}

		this._heap.scramble = this.timer;
		this._heap.scramble2 = 3 + this.sprites[0].x + this.sprites[0].y;
		if (this.meli){
			this._heap.scramble+=this.meli.sprite.x;
			this._heap.scramble^=this.meli.sprite.y;

			this._heap.scramble2 += this.meli.sprite.x;
			this._heap.scramble2 -= this.meli.sprite.y;
		}
		if ( ((this._heap.scramble&2) ^ ((this._heap.scramble&8)>>2) ) && ((this.timer&15) === (this._heap.scramble2&15) ) ){
			if (this._heap.scramble&2) {
				this.intensity = Math.min(this.intensity+1,2);
			}
			else {
				this.intensity = Math.max(this.intensity-1,0);
			}
		}
		if ( ((this._heap.scramble&1) ^ ((this._heap.scramble&4)>>2)  ) && ((this.timer&7)  === (this._heap.scramble2&7)) ){
			if (this._heap.scramble&4) {
				++this.direction;
			}
			else {
				--this.direction;
			}
			// enforced de-signing %8
			this.direction+=8;
			this.direction&=7;
		}

		this._heap.h = this.intensity_map[this.intensity>>(this.meli.grounded?1:0)][this.timer&3];
		this._heap.v = this.intensity_map[Math.max((this.intensity>>(this.meli.grounded?1:0))-1,0)][this.timer&3];

		// in C/++, switch-within-for would be cleaner since switch compiles to a table-jump;
		// since js switch behaves like a chained-if, for-within-switch may be faster
		// than evaluating the switch every iteration
		switch (this.direction){
			case 0:
				for (this._heap.i=0; this._heap.i<this.num_sprites; ++this._heap.i){
					this.sprites[this._heap.i].move(this.intensity,0);
				}
				if (this.meli){
					this.meli.sprite.move(this._heap.h,0);
				}
			break;
			case 1:
				for (this._heap.i=0; this._heap.i<this.num_sprites; ++this._heap.i){
					this.sprites[this._heap.i].move(this.intensity,this.intensity);
				}
				if (this.meli){
					this.meli.sprite.move(this._heap.h,this._heap.v);
				}
			break;
			case 2:
				for (this._heap.i=0; this._heap.i<this.num_sprites; ++this._heap.i){
					this.sprites[this._heap.i].move(0,this.intensity);
				}
				if (this.meli){
					this.meli.sprite.move(0,this._heap.v);
				}
			break;
			case 3:
				for (this._heap.i=0; this._heap.i<this.num_sprites; ++this._heap.i){
					this.sprites[this._heap.i].move(-this.intensity,this.intensity);
				}
				if (this.meli){
					this.meli.sprite.move(-this._heap.h,this._heap.v);
				}
			break;
			case 4:
				for (this._heap.i=0; this._heap.i<this.num_sprites; ++this._heap.i){
					this.sprites[this._heap.i].move(-this.intensity,0);
				}
				if (this.meli){
					this.meli.sprite.move(-this._heap.h,0);
				}
			break;
			case 5:
				for (this._heap.i=0; this._heap.i<this.num_sprites; ++this._heap.i){
					this.sprites[this._heap.i].move(-this.intensity,-this.intensity);
				}
				if (this.meli){
					this.meli.sprite.move(-this._heap.h,-this._heap.v);
				}
			break;
			case 6:
				for (this._heap.i=0; this._heap.i<this.num_sprites; ++this._heap.i){
					this.sprites[this._heap.i].move(0,-this.intensity);
				}
				if (this.meli){
					this.meli.sprite.move(0,-this._heap.v);
				}
			break;
			case 7:
				for (this._heap.i=0; this._heap.i<this.num_sprites; ++this._heap.i){
					this.sprites[this._heap.i].move(this.intensity,-this.intensity);
				}
				if (this.meli){
					this.meli.sprite.move(this._heap.h,-this._heap.v);
				}
			break;
		}

		for (this._heap.i=0; this._heap.i<this.num_sprites; ++this._heap.i){
			if (this.intensity){
				++this.sprite_ages[this._heap.i];
				this.sprite_ages[this._heap.i] &= 255;
				if (!this.sprite_ages[this._heap.i]){
					// sprite x,y reassign
					this.homePos(this.sprites[this._heap.i],this._heap.i);
				}
			}

			this.sprites[this._heap.i].frame = this.direction;
			if (this.intensity&2) this.sprites[this._heap.i].frame+=8;
			this.sprites[this._heap.i].visible = (!!this.intensity)&&(this.sprite_ages[this._heap.i]&32);
		}
		

		++this.timer;
	};