#pragma require "plusSeasonsSummer.pal"
#pragma require "plusSeasonsAutumn.pal"
#pragma require "plusSeasonsWinter.pal"

enum Seasons {Spring, Summer, Autumn, Winter};
uint currSeason = Spring + jjRandom()%4;
int seasonTime = 1050;
float transitionTime = 0;

jjPAL springPal, summerPal, autumnPal, winterPal;

const array<uint16> tilesToUnmask = {721,731,741,751,761,771};

bool frozenLake() {
	return (currSeason == Winter && seasonTime > 140) || (currSeason == Spring && seasonTime < 140 && jjGameTicks > 140);
}

void onLevelLoad() {
	jjAnimSets[ANIM::PLUS_SCENERY].load();
	jjUseLayer8Speeds = true;
	jjWeapons[WEAPON::SEEKER].comesFromGunCrates = false;
	jjWeapons[WEAPON::GUN8].comesFromGunCrates = jjWeapons[WEAPON::GUN9].comesFromGunCrates = true;
	jjWaterLighting = WATERLIGHT::GLOBAL;
	jjSetWaterLevel(47*32, true);
	
	jjANIMATION@ anim = jjAnimations[jjAnimSets[ANIM::PLUS_SCENERY] + 0];
	for (uint j = 0; j < anim.frameCount; j++) {
		jjANIMFRAME@ frame = jjAnimFrames[anim + j];
		jjPIXELMAP sprite(frame);
		for (uint x = 0; x < sprite.width; ++x) {
			for (uint y = 0; y < sprite.height; ++y) {
				if (sprite[x,y] >= 80 && sprite[x,y] <= 87) sprite[x,y] = 128 + (sprite[x,y]&7)*2;
			}
		}
		sprite.save(frame);
	}
	
	jjPIXELMAP surface(69);
	surface.save(248);

	for (uint i = 0; i < tilesToUnmask.length(); i++)
		jjMASKMAP().save(tilesToUnmask[i], true);
		
	springPal.load("Diam1.j2t");
	summerPal.load("plusSeasonsSummer.pal");
	autumnPal.load("plusSeasonsAutumn.pal");
	winterPal.load("plusSeasonsWinter.pal");
	
	jjOBJ@ turtles = jjObjectPresets[OBJECT::NORMTURTLE];
	turtles.playerHandling = HANDLING::PARTICLE;
	turtles.behavior = NonEnemyTurtle;
	turtles.isTarget = turtles.isFreezable = turtles.isBlastable = turtles.triggersTNT = false;
}

void setSeasonPalette() {
	switch (currSeason) {
		case Spring:
			springPal.apply(); 
			jjSetFadeColors(0,50,200);
			break;
		case Summer:
			summerPal.apply();
			jjSetFadeColors(125,200,250);
			jjSetWaterLevel(56*32, true);
			break;
		case Autumn: 
			autumnPal.apply();
			jjSetFadeColors(125,100,200);
			break;
		case Winter: 
			winterPal.apply();
			jjSetFadeColors(75,75,175);
			break;
	}
}

void onLevelBegin() {
	setSeasonPalette();
	
	if (!jjIsServer)
		jjSendPacket(jjSTREAM()); //send an empty packet to request an update from the server
}

void onReceive(jjSTREAM &in packet, int clientID) {
	if (jjIsServer) {
		updateSeason(clientID);
	} else {
		uint season;
		int time;
		packet.pop(season);
		packet.pop(time);
		
		currSeason = season;
		seasonTime = time;
		setSeasonPalette();
	}
}

void updateSeason(int clientID) {
	jjSTREAM packet;
	packet.push(currSeason);
	packet.push(seasonTime);
	jjSendPacket(packet, clientID);
}

void onMain() {
	jjWaterLayer = jjLowDetail? 9:1;

	jjIsSnowingOutdoorsOnly = true;
	jjIsSnowing = currSeason == Summer? false : !jjLowDetail;
	
	seasonTime++;
	switch (currSeason) {
		case Spring:
			jjSnowingType = SNOWING::RAIN;
			jjSnowingIntensity = 1;
			if (seasonTime >= 140) {
				setPalette(springPal);
				setFadeColors(0,50,200);
				jjSetWaterLevel(47*32, false);
			}
			break;
		case Summer:
			if (seasonTime >= 140) {
				setPalette(summerPal);
				setFadeColors(125,200,250);
			}
			if (seasonTime >= 175) {
				jjSetWaterLevel(56*32, false);
			}
			break;
		case Autumn:
			jjSnowingType = SNOWING::LEAF;
			jjSnowingIntensity = 0;
			if (seasonTime >= 140) {
				setPalette(autumnPal);
				setFadeColors(125,100,200);
				jjSetWaterLevel(47*32, false);
			}
			break;
		case Winter:
			jjSnowingType = SNOWING::FLOWER;
			jjSnowingIntensity = 2;
			if (seasonTime >= 140) {
				setPalette(winterPal);
				setFadeColors(75,75,175);
			}
			break;
		default: break;
	}
	if (seasonTime == 30*70) {
		currSeason++;
		seasonTime = 0;
		transitionTime = 0;
	}
	if (currSeason > Winter) currSeason = Spring;
	
	if (frozenLake()) jjSetWaterLevel(47*32, true); 
	
	jjMASKMAP surface(248);
	for (uint x = 0; x <= 32; ++x)
		for (uint y = 0; y <= 32; ++y)
			surface[x,y] = frozenLake()? true:false;
	surface.save(248, true);
}

void setPalette(jjPAL@ pal) {
	if (transitionTime < 500) transitionTime++;
	jjPalette.copyFrom(96, 159, 96, pal, transitionTime / 500);
	jjPalette.apply();
}

void setFadeColors(uint R, uint G, uint B) {
	jjPALCOLOR fade = jjGetFadeColors();
	
	if (fade.red < R) fade.red++;
	else if (fade.red > R) fade.red--;
	if (fade.green < G) fade.green++;
	else if (fade.green > G) fade.green--;
	if (fade.blue < B) fade.blue++;
	else if (fade.blue > B) fade.blue--;
	
	jjSetFadeColors(fade.red, fade.green, fade.blue);
}

void onPlayer(jjPLAYER@ play) {
	if (play.shieldTime > 15*70) play.shieldTime = 15*70;
	if (play.lighting > 70) {
		if (currSeason == Summer) play.lighting = 110;
		if (currSeason == Spring || currSeason == Winter) play.lighting = 85;
	} else {
		if (play.lighting == 70 && currSeason == Winter) play.lighting = 60;
	}
	
	if (play.lighting > 100 && currSeason != Summer) play.lighting = 100;
	
	if (frozenLake() && play.yPos > int(jjWaterLevel + 8) && play.health > 0) {
		play.kill();
		jjAlert("||You died in the icy waters...", false, STRING::MEDIUM);
	}
}

void onDrawLayer2(jjPLAYER@ play, jjCANVAS@ canvas) {
	if (jjLowDetail) canvas.drawRectangle(0, int(jjWaterLevel), jjLayerWidth[2]*32, jjLayerHeight[2]*32 - int(jjWaterLevel), 36, SPRITE::TRANSLUCENT);
}

void onFunction1(jjPLAYER@ play) {
	play.warpToID(1);
	play.timerStart(8*70);
}

void onFunction2(jjPLAYER@ play) {
	play.warpToID(2);
	play.timerStart(8*70);
}

void onFunction3(jjPLAYER@ play) {
	play.warpToID(3);
	play.timerStop();
}

void onFunction4(jjPLAYER@ play) {
	play.lighting = currSeason == Winter? 60:70;
}

void onFunction5(jjPLAYER@ play) {
	if (currSeason == Summer) play.lighting = 110;
	else play.lighting = currSeason == Spring || currSeason == Winter? 85:100;
}

void onPlayerTimerEnd(jjPLAYER@ play) {
	play.warpToID(3);
	play.timerStop(); 
}

void onDrawLayer4(jjPLAYER@ play, jjCANVAS@ canvas) {
	if (frozenLake()) {
		for (int i = 2944; i < 3520; i += 32) {
			canvas.drawSprite(i, int(jjWaterLevel)+16, ANIM::DESTSCEN, 4, 0, 0, SPRITE::FROZEN);
		}
	}
}

void onFunction6(jjPLAYER@ play, uint8 textID) {
	const uint16 tileX = uint16(play.xPos / 32), tileY = uint16(play.yPos / 32);
	if (jjTileGet(4, tileX, tileY) != 0) {
		play.showText(textID, 0);
		jjTileSet(4, tileX, tileY, 0);
		jjTileSet(4, tileX, tileY + 1, 31);
	}
}

void NonEnemyTurtle(jjOBJ@ obj) {
	if (obj.state == STATE::START)
		obj.behave(BEHAVIOR::WALKINGENEMY);
	if (obj.counter > 0) {
		if (currSeason == Spring) {
			if (obj.counter == 63)
				jjSample(obj.xPos, obj.yPos, SOUND::TURTLE_TURN);
			--obj.counter;
		}
		else if (obj.counter < 63)
			++obj.counter;
		obj.curFrame = jjAnimations[jjAnimSets[ANIM::TURTLE].firstAnim + 2].firstFrame + (obj.counter / 10);
		obj.draw();
	} else if (currSeason == Winter) {
		obj.counter = 1;
		jjSample(obj.xPos, obj.yPos, SOUND::TURTLE_HIDE);
		obj.draw();
	} else {
		obj.behave(BEHAVIOR::WALKINGENEMY);
		if (jjRandom() & 127 == 0)
			jjSample(obj.xPos, obj.yPos, SOUND::Sample(SOUND::TURTLE_SPK1TURT + (jjRandom() & 3)));
	}
}