package com.ld50.game;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;

import java.util.Iterator;

import Global.Global;
import entities.Bullet;
import entities.Furbal;
import entities.Gunfire;
import entities.PausePerson;
import entities.Player;
import levelGen.Glass;
import levelGen.Glass.State;
import levelGen.Level;
import u.UsefulMethods;

public class GameScreen implements Screen {
	final HF game;

	private Music levelMusic;
	private OrthographicCamera camera;
	private Viewport vport;
	private Player player;
	int currentFrame = 1;
	int MAX_FRAMES = 5;
	private Level level;
	public int sw = 1440;
	public int sh = 720;
	private int cameraMoveTimer = 25;
	// all the glass:
	private Array<Glass> glassTop;
	private Array<Glass> glassBottom;
	private Array<Glass> glassLeft;
	private Array<Glass> glassRight;
	private Glass glassBottomRight;
	private Glass glassBottomLeft;
	private Glass glassUpperLeft;
	private Glass glassUpperRight;
	private Array<Bullet> bullets;
	private Array<Furbal> furbalsRight;
	private Array<Furbal> furbalsLeft;
	private Array<Furbal> furbalsTop;
	private Array<Furbal> furbalsBottom;
	private Array<Bullet> bullets2;
	private Array<Gunfire> gunfires;
	private Array<Gunfire> gunfires2;
	private Vector3 pos23;
	// add pause person. This is added to ever screen in the game you want a pause menu.
	private PausePerson pp;
	private Sound enter;
	private Sound enter2;
	// other sfx
	private Sound glassPaneHit;
	private Sound glassPaneHit2;
	private Sound glassPaneHit3;
	private Sound glassPaneHit4;
	private Sound glassPaneHit5;
	private Sound glassPaneHit6;
	private Sound glassPaneHit7;
	private Sound glassPaneHit8;
	private Sound glassPaneHit9;
	private Sound glassPaneHit10;
	private Sound hit;
	private Sound death;

	private int isDeadTimer = 40;
	private int numberOfLeftFurbals;
	private int numberOfRightFurbals;
	private int numberOfTopFurbals;
	private int numberOfBottomFurbals;
	private int leftFurbalSpawnTimer;
	private int rightFurbalSpawnTimer;
	private int topFurbalSpawnTimer;
	private int bottomFurbalSpawnTimer;
	private int rateOfLeftFurbalSpawns = 100;
	private int rateOfRightFurbalSpawns = 100;
	private int rateOfTopFurbalSpawns = 100;
	private int rateOfBottomFurbalSpawns = 100;
	private int rightModulo = MathUtils.random(80, 250);
	private int leftModulo = MathUtils.random(80, 250);
	private int topModulo = MathUtils.random(80, 250);
	private int bottomModulo = MathUtils.random(80, 250);
	private int gameTimer = 0;

	private boolean goal;

	public GameScreen(final HF game) {
		this.game = game;
		// camera
		camera = new OrthographicCamera();
		vport = new FitViewport(sw, sh, camera);
		// level
		level = new Level(HF.LW, HF.LH);// was 64,64
		player = new Player((int) Global.P.x, (int) Global.P.y);// this places the player exactly in the middle of the map.(because it's setin the level gen)
		AddInAllTheGlass();
		// sounds
		// music
		levelMusic = Gdx.audio.newMusic(Gdx.files.internal("menu.ogg"));
		levelMusic.setLooping(true);
		camera.position.set(vport.getWorldWidth() / 2, vport.getWorldHeight() / 2, 0);

		furbalsLeft = new Array<Furbal>();
		for (int x = 0; x < 500; x++) {// was 500
			furbalsLeft.add(new Furbal(9000, 9000, "right"));
		}
		furbalsTop = new Array<Furbal>();
		for (int x = 0; x < 500; x++) {// was 500
			furbalsTop.add(new Furbal(9000, 9000, "down"));
		}
		furbalsBottom = new Array<Furbal>();
		for (int x = 0; x < 500; x++) {// was 500
			furbalsBottom.add(new Furbal(9000, 9000, "up"));
		}
		furbalsRight = new Array<Furbal>();
		for (int x = 0; x < 500; x++) {// was 500
			furbalsRight.add(new Furbal(9000, 9000, "left"));
		}
		bullets = new Array<Bullet>();
		for (int x = 0; x < 15; x++) {
			bullets.add(new Bullet(10000, 10000));
		}
		gunfires = new Array<Gunfire>();
		for (int x = 0; x < 15; x++) {
			gunfires.add(new Gunfire(10000, 10000));
		}
		bullets2 = new Array<Bullet>();
		for (int x = 0; x < 15; x++) {
			bullets2.add(new Bullet(10000, 10000));
		}
		gunfires2 = new Array<Gunfire>();
		for (int x = 0; x < 15; x++) {
			gunfires2.add(new Gunfire(10000, 10000));
		}
		// font
		HF.Score = 0;
		// sfx
		glassPaneHit = Gdx.audio.newSound(Gdx.files.internal("sfx/glassPaneHit.ogg"));
		glassPaneHit2 = Gdx.audio.newSound(Gdx.files.internal("sfx/glassPaneHit2.ogg"));
		glassPaneHit3 = Gdx.audio.newSound(Gdx.files.internal("sfx/glassPaneHit3.ogg"));
		glassPaneHit4 = Gdx.audio.newSound(Gdx.files.internal("sfx/glassPaneHit4.ogg"));
		glassPaneHit5 = Gdx.audio.newSound(Gdx.files.internal("sfx/glassPaneHit5.ogg"));
		glassPaneHit6 = Gdx.audio.newSound(Gdx.files.internal("sfx/glassPaneHit6.ogg"));
		glassPaneHit7 = Gdx.audio.newSound(Gdx.files.internal("sfx/glassPaneHit7.ogg"));
		glassPaneHit8 = Gdx.audio.newSound(Gdx.files.internal("sfx/glassPaneHit8.ogg"));
		glassPaneHit9 = Gdx.audio.newSound(Gdx.files.internal("sfx/glassPaneHit9.ogg"));
		glassPaneHit10 = Gdx.audio.newSound(Gdx.files.internal("sfx/glassPaneHit10.ogg"));
		hit = Gdx.audio.newSound(Gdx.files.internal("sfx/hit.ogg"));
		death = Gdx.audio.newSound(Gdx.files.internal("sfx/death.ogg"));
		// add pause person. This is added to every screen in the game you want a pause menu.
		pp = new PausePerson(Gdx.graphics.getWidth() - 1010f, Gdx.graphics.getHeight() - 240f);
		enter = Gdx.audio.newSound(Gdx.files.internal("sfx/enter.ogg"));
		enter2 = Gdx.audio.newSound(Gdx.files.internal("sfx/enter2.ogg"));
	}

	private void AddInAllTheGlass() {
		float tw = HF.TW * HF.TTW;// true width(best guess lol)
		float th = HF.TH * HF.TTH;// true height(best guess lol)
		float _ox = HF.TW;
		float _oy = HF.TH;
		glassTop = new Array<Glass>();
		for (float x = -tw + _ox; x <= tw - _ox; x += HF.TW) {
			glassTop.add(new Glass(x, th, State.UP));
		}
		glassBottom = new Array<Glass>();
		for (float x = -tw + _ox; x <= tw - _ox; x += HF.TW) {
			glassBottom.add(new Glass(x, -th, State.DOWN));
		}
		glassLeft = new Array<Glass>();
		for (float y = -th + _oy; y <= th - _oy; y += HF.TH * 2) {
			glassLeft.add(new Glass(-tw, y, State.LEFT));
		}
		glassRight = new Array<Glass>();
		for (float y = -th + _oy; y <= th - _oy; y += HF.TH * 2) {
			glassRight.add(new Glass(tw, y, State.RIGHT));
		}
		glassBottomRight = new Glass(tw, -th, State.BOTTOMRIGHT);
		glassBottomLeft = new Glass(-tw, -th, State.BOTTOMLEFT);
		glassUpperLeft = new Glass(-tw, th, State.UPPERLEFT);
		glassUpperRight = new Glass(tw, th, State.UPPERRIGHT);
	}

	private void RenderAllTheGlass(HF game, OrthographicCamera camera, float dt) {
		for (int d = 0; d < glassTop.size; d++) {
			glassTop.get(d).render(game, camera, dt);
		}
		for (int d = 0; d < glassLeft.size; d++) {
			glassLeft.get(d).render(game, camera, dt);
		}
		for (int d = 0; d < glassRight.size; d++) {
			glassRight.get(d).render(game, camera, dt);
		}
		glassUpperRight.render(game, camera, dt);
		glassUpperLeft.render(game, camera, dt);
	}

	public void update(float dt) {
		if (player.isDying) {
			// don't move camera. :D ?? maybe?
			if (cameraMoveTimer > 0) {
				cameraMoveTimer--;
				UsefulMethods.MoveCameraAroundRandomly(camera);
			}
		} else {
			// System.out.println("cameraX: " + camera.position.x + " cameraY: " + camera.position.y);
			// System.out.println("getGraphicsWidth : " + (Gdx.graphics.getWidth()));
			// System.out.println("getGraphicsHeight: " + Gdx.graphics.getHeight());
			// System.out.println("Level width: " + level.w * HF.TW);
			// System.out.println("Level height:" + level.h * HF.TH);
			/*
			 * if (camera.position.x <= 0) camera.position.x = 1; else if (camera.position.x >= level.w * HF.TW - (Gdx.graphics.getWidth() / 2))
			 * camera.position.x = level.w * HF.TW - (Gdx.graphics.getWidth() / 2) - 1; else camera.position.x = player.rect.x; if (camera.position.y > level.h
			 * * HF.TH - (Gdx.graphics.getHeight() / 2)) camera.position.y = level.h * HF.TH - (Gdx.graphics.getHeight() / 2) - 1; else if (camera.position.y <
			 * 0) camera.position.y = 1; else camera.position.y = player.rect.y;
			 */
			camera.position.x = (int) player.rect.x;
			camera.position.y = (int) player.rect.y;

		}
		gameTimer++;
		camera.update();
	}

	@Override
	public void show() {
		Gdx.input.setInputProcessor(new InputAdapter() {
			@Override
			public boolean keyDown(int keyCode) {
				// add this first part for the pause portion of the screen. The escape button. Otherwise retain the space control.
				// Maybe we'll have a clickable button on the bottom side for options?
				if (keyCode == Input.Keys.ESCAPE && !Global.IsPaused) {
					if (!Global.SetVolumeToZero)
						enter.play(2f);
					Global.IsPaused = true;
				} else if (keyCode == Input.Keys.ESCAPE && Global.IsPaused && Global.IsKeyBindings && Global.IsSetKey) {
					if (!Global.SetVolumeToZero)
						enter2.play(2f);
					Global.IsSetKey = false;
				} else if (keyCode == Input.Keys.ESCAPE && Global.IsPaused && Global.IsKeyBindings) {
					if (!Global.SetVolumeToZero)
						enter2.play(2f);
					Global.IsKeyBindings = false;
					pp.IsSwitchingToKeyBindings = true;
				} else if (keyCode == Input.Keys.ESCAPE && Global.IsPaused) {
					if (!Global.SetVolumeToZero)
						enter2.play(2f);
					Global.IsPaused = false;
				}
				if (Global.IsSetKey)
					Global.KeycodeSet = keyCode;
				return true;
			}

			@Override
			public boolean touchDown(int x, int y, int pointer, int button) {// this is for capturing mouse clicks
				if (Global.IsSetKey && Global.IsPaused)
					Global.KeycodeSet = button;
				return true;
			}

		});
		// start the play back of the background music
		// when the screen is shown
		levelMusic.setVolume(1f);
		if (!Global.IsMusicPaused)
			levelMusic.play();
	}

	@Override
	public void render(float delta) {
		ScreenUtils.clear(0, 0, 0, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		game.batch.setProjectionMatrix(camera.combined);
		game.batch.begin();
		// System.out.println("game batch begin has been called. " + game.batch + " see? ");
		if (Global.IsPaused) {
			camera.position.y = Gdx.graphics.getHeight() * .5f;
			camera.position.x = Gdx.graphics.getWidth() * .5f;
			camera.update();
			// System.out.println("cameraX: " + camera.position.x + " cameraY: " + camera.position.y);
			pp.RenderEntirePauseMenu(delta, game, game.font, levelMusic, camera);

			// DebugRenderer.DrawDebugRectangle(pp.saveGameRect, Color.RED, camera.combined);//there were a lot more of these heheeh
		} else {
			// System.out.println("this should run before level.render");
			// draw level
			level.render(game, camera);
			// draw player
			game.batch.setColor(player.color);// set color before you draw
			// DebugRenderer.DrawDebugRectangle(player.rect, Color.RED, camera.combined);// there were a lot more of these heheeh
			game.batch.draw(player.getFrame(delta, camera), player.rect.x - 24, player.rect.y - 4);
			pos23 = camera.unproject(new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0));
			// draw bullets
			for (int d = 0; d < bullets.size; d++) {
				if (Player.firesGun) {
					if (Player.r) {
						bullets.get(d).FireBullet(Global.P.x + MathUtils.random(40, 80), Global.P.y + MathUtils.random(20, 50), pos23.x, pos23.y);
						gunfires.get(d).FireBullet(Global.P.x + MathUtils.random(40, 80), Global.P.y + MathUtils.random(1, 40));
					} else if (Player.l) {
						bullets.get(d).FireBullet(Global.P.x + MathUtils.random(10, 30), Global.P.y + MathUtils.random(20, 50), pos23.x, pos23.y);
						gunfires.get(d).FireBullet(Global.P.x + MathUtils.random(-40, -20), Global.P.y + MathUtils.random(1, 40));
					} else if (Player.u) {
						bullets.get(d).FireBullet(Global.P.x + MathUtils.random(10, 40), Global.P.y + MathUtils.random(30, 70), pos23.x, pos23.y);
						gunfires.get(d).FireBullet(Global.P.x + MathUtils.random(-20, 30), Global.P.y + MathUtils.random(30, 70));
					} else if (Player.d) {
						bullets.get(d).FireBullet(Global.P.x + MathUtils.random(10, 40), Global.P.y + MathUtils.random(1, 40), pos23.x, pos23.y);
						gunfires.get(d).FireBullet(Global.P.x + MathUtils.random(-20, 30), Global.P.y + MathUtils.random(-40, -20));
					}
				}
				if (d + 1 == bullets.size) {// end of loop
					Player.firesGun = false;
					Player.outOfAmmo1 = true;
				}
				game.batch.setColor(bullets.get(d).color);
				// DebugRenderer.DrawDebugRectangle(bullets.get(d).rect, Color.YELLOW, camera.combined);// there were a lot more of these heheeh
				bullets.get(d).render(game, delta);
				game.batch.setColor(gunfires.get(d).color);
				gunfires.get(d).render(game, delta);
				if (bullets.get(d).isDead)
					Player.outOfAmmo1 = false;
			}
			// draw bullets
			for (int d = 0; d < bullets2.size; d++) {
				if (Player.firesGun2) {
					if (Player.r) {
						bullets2.get(d).FireBullet(Global.P.x + MathUtils.random(40, 80), Global.P.y + MathUtils.random(20, 50), pos23.x, pos23.y);
						gunfires2.get(d).FireBullet(Global.P.x + MathUtils.random(40, 80), Global.P.y + MathUtils.random(1, 40));
					} else if (Player.l) {
						bullets2.get(d).FireBullet(Global.P.x + MathUtils.random(10, 30), Global.P.y + MathUtils.random(20, 50), pos23.x, pos23.y);
						gunfires2.get(d).FireBullet(Global.P.x + MathUtils.random(-40, -20), Global.P.y + MathUtils.random(1, 40));
					} else if (Player.u) {
						bullets2.get(d).FireBullet(Global.P.x + MathUtils.random(10, 40), Global.P.y + MathUtils.random(30, 70), pos23.x, pos23.y);
						gunfires2.get(d).FireBullet(Global.P.x + MathUtils.random(-20, 30), Global.P.y + MathUtils.random(30, 70));
					} else if (Player.d) {
						bullets2.get(d).FireBullet(Global.P.x + MathUtils.random(10, 40), Global.P.y + MathUtils.random(1, 40), pos23.x, pos23.y);
						gunfires2.get(d).FireBullet(Global.P.x + MathUtils.random(-20, 30), Global.P.y + MathUtils.random(-40, -20));
					}
				}
				if (d + 1 == bullets2.size) {// end of loop
					Player.firesGun2 = false;
					Player.outOfAmmo2 = true;
				}
				game.batch.setColor(Color.WHITE);// bullets2.get(d).color);
				bullets2.get(d).render(game, delta);
				game.batch.setColor(gunfires2.get(d).color);
				gunfires2.get(d).render(game, delta);
				if (bullets2.get(d).isDead)
					Player.outOfAmmo2 = false;
			}
			// GLASSSSSSSSSSSSSSSSSSSSSSSSSSS
			// render the bottom glass panels because they are actually below the little furbals
			for (int d = 0; d < glassBottom.size; d++) {
				glassBottom.get(d).render(game, camera, delta);
			}
			glassBottomRight.render(game, camera, delta);
			glassBottomLeft.render(game, camera, delta);
			// draw furbals
			if (topFurbalSpawnTimer <= 0) {
				numberOfTopFurbals += 2;
				topFurbalSpawnTimer = rateOfTopFurbalSpawns;
			}
			if (topFurbalSpawnTimer > 0)
				topFurbalSpawnTimer--;
			if (gameTimer % topModulo == 0) {
				rateOfTopFurbalSpawns--;
			}
			for (int d = 0; d < furbalsTop.size; d++) {
				if (furbalsTop.get(d).isDead) {
					if (numberOfTopFurbals > 0) {
						numberOfTopFurbals--;
						furbalsTop.get(d).isDead = false;
						furbalsTop.get(d).isDying = false;
						furbalsTop.get(d).isDyingTimer = 100;
						furbalsTop.get(d).SpawnFurbal((int) Global.P.x + MathUtils.random(-HF.TW * HF.TTW - HF.TW, HF.TW * HF.TTW),
								(int) Global.P.y + MathUtils.random(HF.TH * HF.TTH + 1000, HF.TH * HF.TTH + 1500), "down");
					}
				}
				game.batch.setColor(furbalsTop.get(d).color);
				// DebugRenderer.DrawDebugRectangle(furbals.get(d).rect, Color.YELLOW, camera.combined);// there were a lot more of these heheeh
				furbalsTop.get(d).render(game, delta);
			}
			if (bottomFurbalSpawnTimer <= 0) {
				numberOfBottomFurbals += 2;
				bottomFurbalSpawnTimer = rateOfBottomFurbalSpawns;
			}
			if (bottomFurbalSpawnTimer > 0)
				bottomFurbalSpawnTimer--;
			if (gameTimer % bottomModulo == 0) {
				rateOfBottomFurbalSpawns--;
			}
			for (int d = 0; d < furbalsBottom.size; d++) {
				if (furbalsBottom.get(d).isDead) {
					if (numberOfBottomFurbals > 0) {
						numberOfBottomFurbals--;
						furbalsBottom.get(d).isDead = false;
						furbalsBottom.get(d).isDying = false;
						furbalsBottom.get(d).isDyingTimer = 100;
						furbalsBottom.get(d).SpawnFurbal((int) Global.P.x + MathUtils.random(-HF.TW * HF.TTW - HF.TW, HF.TW * HF.TTW),
								(int) Global.P.y + MathUtils.random(-HF.TH * HF.TTH - 1500, -HF.TH * HF.TTH - 1000), "up");
					}
				}
				game.batch.setColor(furbalsBottom.get(d).color);
				// DebugRenderer.DrawDebugRectangle(furbals.get(d).rect, Color.YELLOW, camera.combined);// there were a lot more of these heheeh
				furbalsBottom.get(d).render(game, delta);
			}
			// System.out.println("rightFurbalSpawnTimer: " + rightFurbalSpawnTimer);
			// System.out.println("rateOfRightFurbalSpawns: " + rateOfRightFurbalSpawns);
			// System.out.println("numberOfRightFurbals: " + numberOfRightFurbals);
			if (rightFurbalSpawnTimer <= 0) {
				numberOfRightFurbals += 2;
				rightFurbalSpawnTimer = rateOfRightFurbalSpawns;
			}
			if (rightFurbalSpawnTimer > 0)
				rightFurbalSpawnTimer--;
			if (gameTimer % rightModulo == 0) {
				rateOfRightFurbalSpawns--;
			}
			for (int d = 0; d < furbalsRight.size; d++) {
				if (furbalsRight.get(d).isDead) {
					if (numberOfRightFurbals > 0) {
						numberOfRightFurbals--;
						furbalsRight.get(d).isDead = false;
						furbalsRight.get(d).isDying = false;
						furbalsRight.get(d).isDyingTimer = 100;
						furbalsRight.get(d).SpawnFurbal((int) Global.P.x + MathUtils.random(HF.TW * HF.TTW + 1000, HF.TW * HF.TTW + 1500),
								(int) Global.P.y + MathUtils.random(-HF.TH * HF.TTH, HF.TH * HF.TTH), "left");
					}
				}
				game.batch.setColor(furbalsRight.get(d).color);
				// DebugRenderer.DrawDebugRectangle(furbals.get(d).rect, Color.YELLOW, camera.combined);// there were a lot more of these heheeh
				furbalsRight.get(d).render(game, delta);
			}
			if (leftFurbalSpawnTimer <= 0) {
				numberOfLeftFurbals += 2;
				leftFurbalSpawnTimer = rateOfLeftFurbalSpawns;
			}
			if (leftFurbalSpawnTimer > 0)
				leftFurbalSpawnTimer--;
			if (gameTimer % leftModulo == 0) {
				rateOfLeftFurbalSpawns--;
			}
			for (int d = 0; d < furbalsLeft.size; d++) {
				if (furbalsLeft.get(d).isDead) {
					if (numberOfLeftFurbals > 0) {
						numberOfLeftFurbals--;
						furbalsLeft.get(d).isDead = false;
						furbalsLeft.get(d).isDying = false;
						furbalsLeft.get(d).isDyingTimer = 100;
						furbalsLeft.get(d).SpawnFurbal((int) Global.P.x + MathUtils.random(-HF.TW * HF.TTW - 1500, -HF.TW * HF.TTW - 1000),
								(int) Global.P.y + MathUtils.random(-HF.TH * HF.TTH, HF.TH * HF.TTH), "right");
					}
				}
				game.batch.setColor(furbalsLeft.get(d).color);
				// DebugRenderer.DrawDebugRectangle(furbals.get(d).rect, Color.YELLOW, camera.combined);// there were a lot more of these heheeh
				furbalsLeft.get(d).render(game, delta);
			}
			RenderAllTheGlass(game, camera, delta);
			// draw HUD
			game.font.setColor(Color.BLACK);// set color before you draw
			game.font.draw(game.batch, "Score: " + HF.Score, camera.position.x - HF.MW / 2 + 22, camera.position.y + HF.MH / 2 - 16);// shadow
			game.font.setColor(Color.WHITE);
			game.font.draw(game.batch, "Score: " + HF.Score, camera.position.x - HF.MW / 2 + 20, camera.position.y + HF.MH / 2 - 14);

			game.font.setColor(Color.BROWN);// set color before you draw
			game.font.draw(game.batch, "Health: " + HF.Health, camera.position.x - HF.MW / 2 + 604, camera.position.y + HF.MH / 2 - 18);// shadow
			game.font.setColor(Color.RED);// set color before you draw
			game.font.draw(game.batch, "Health: " + HF.Health, camera.position.x - HF.MW / 2 + 602, camera.position.y + HF.MH / 2 - 16);// shadow
			game.font.setColor(Color.WHITE);
			game.font.draw(game.batch, "Health: " + HF.Health, camera.position.x - HF.MW / 2 + 600, camera.position.y + HF.MH / 2 - 14);
			game.font.setColor(Color.BLACK);
			// debug info:
			game.font.draw(game.batch, "GameTime: " + gameTimer, camera.position.x - HF.MW / 2 + 20, camera.position.y + HF.MH / 2 - 47);// shadow
			game.font.setColor(Color.BLUE);
			game.font.draw(game.batch, "GameTime: " + gameTimer, camera.position.x - HF.MW / 2 + 18, camera.position.y + HF.MH / 2 - 45);
			game.font.setColor(Color.BLACK);
			game.font.draw(game.batch, "Goal Time: 10001", camera.position.x - HF.MW / 2 + 20, camera.position.y + HF.MH / 2 - 77);// shadow
			if (!goal)
				game.font.setColor(Color.PURPLE);
			else
				game.font.setColor(Color.YELLOW);
			game.font.draw(game.batch, "Goal Time: 10001", camera.position.x - HF.MW / 2 + 18, camera.position.y + HF.MH / 2 - 75);
			game.font.setColor(Color.BLACK);
			// game.font.draw(game.batch, "FPS: " + Gdx.graphics.getFramesPerSecond(), camera.position.x - HF.MW / 2 + 20, camera.position.y + HF.MH / 2 -
			// 47);// shadow
			// game.font.setColor(Color.WHITE);
			// game.font.draw(game.batch, "FPS: " + Gdx.graphics.getFramesPerSecond(), camera.position.x - HF.MW / 2 + 18, camera.position.y + HF.MH / 2 - 45);
			// game.font.setColor(Color.BLACK);
			// game.font.draw(game.batch, "JavaMem: " + Gdx.app.getJavaHeap(), camera.position.x + 320, camera.position.y - 297);// SL
			// game.font.setColor(Color.WHITE);
			// game.font.draw(game.batch, "JavaMem: " + Gdx.app.getJavaHeap(), camera.position.x + 328, camera.position.y - 295);
			// game.font.setColor(Color.BLACK);
			// game.font.draw(game.batch, "NativMem: " + Gdx.app.getNativeHeap(), camera.position.x + 320, camera.position.y - 267);// SL
			// game.font.setColor(Color.WHITE);
			// game.font.draw(game.batch, "NativMem: " + Gdx.app.getNativeHeap(), camera.position.x + 328, camera.position.y - 265);
			// game.font.draw(game.batch, "NativMem: " + Gdx.app.getNativeHeap(), camera.position.x + 328, camera.position.y - 265);
			// game.font.setColor(Color.BLACK);
			// end debug info
			// timer till extraction
			/*
			 * game.font.setColor(Color.CYAN); game.font.draw(game.batch, "Time till Extraction: " + HF.ExtractionTimer, camera.position.x - 300,
			 * camera.position.y + 340); game.font.setColor(Color.WHITE); game.font.draw(game.batch, "Time till Extraction: " + HF.ExtractionTimer,
			 * camera.position.x - 301, camera.position.y + 342);
			 */

			game.batch.end();
			// debug drawing section: this IS important. I'm glad this is starting to make sense. It's handled on a different batch render call.
			// DrawDebugLine(posV2, mousePosV2, 2, Color.CORAL, camera.combined);
			// DrawDebugRectangle(growl.rect, Color.BLUE, camera.combined);
			// DrawDebugBoundingBox(player.box, Color.YELLOW, camera.combined);
			// DrawDebugBoundingBox(rbox, Color.RED, camera.combined);
			checkFurbalsCollisions(furbalsTop);
			checkFurbalsCollisions(furbalsBottom);
			checkFurbalsCollisions(furbalsRight);
			checkFurbalsCollisions(furbalsLeft);

			checkBulletsCollisionsWithGlass(bullets);
			checkBulletsCollisionsWithGlass(bullets2);

			if (Gdx.input.isKeyJustPressed(Input.Keys.Q)) {// reset map or screen
				// dispose();// hee hee i figured out how to reset the level. xD (dispose of the level and reload it. ;-) )
				// game.setScreen(new GameScreen(game));
			}
			// end game:
			if (HF.Health <= 0 && isDeadTimer <= 0 && !goal) {
				camera.position.y = 0;
				camera.position.x = 0;
				camera.update();
				dispose();
				game.setScreen(new LoseScreen(game));
			}
			if (HF.Health <= 0 && isDeadTimer > 0) {
				isDeadTimer--;
				death.play();
				player.isDying = true;
			}
			if (gameTimer >= 10001)
				goal = true;
			if (goal && isDeadTimer <= 0) {
				camera.position.y = 0;
				camera.position.x = 0;
				camera.update();
				dispose();
				game.setScreen(new WinScreen(game));
			}
			update(delta);// going to set camera position to last. :-)
		}

	}// end of render (or update)

	public void checkFurbalsCollisions(Array<Furbal> furbals) {
		for (Iterator<Furbal> iter = furbals.iterator(); iter.hasNext();) {
			Furbal furb = iter.next();
			for (Iterator<Glass> iter2 = glassTop.iterator(); iter2.hasNext();) {
				Glass gla = iter2.next();
				if (gla.health > 0 && furb.rect.overlaps(gla.rect)) {
					furb.isCollidingWithGlass = true;
					if (furb.canHit) {
						furb.canHit = false;
						gla.health--;
						playRandomGlassPanelHitSound(10);
						HF.Score += 2;// testing score (remove this!)
					}
				}
			}
			for (Iterator<Glass> iter3 = glassBottom.iterator(); iter3.hasNext();) {
				Glass gla = iter3.next();
				if (gla.health > 0 && furb.rect.overlaps(gla.rect)) {
					furb.isCollidingWithGlass = true;
					if (furb.canHit) {
						furb.canHit = false;
						gla.health--;
						playRandomGlassPanelHitSound(10);
						HF.Score += 2;// testing score (remove this!)
					}
				}
			}
			for (Iterator<Glass> iter4 = glassLeft.iterator(); iter4.hasNext();) {
				Glass gla = iter4.next();
				if (gla.health > 0 && furb.rect.overlaps(gla.rect)) {
					furb.isCollidingWithGlass = true;
					if (furb.canHit) {
						furb.canHit = false;
						gla.health--;
						playRandomGlassPanelHitSound(10);
						HF.Score += 2;// testing score (remove this!)
					}
				}
			}
			for (Iterator<Glass> iter5 = glassRight.iterator(); iter5.hasNext();) {
				Glass gla = iter5.next();
				if (gla.health > 0 && furb.rect.overlaps(gla.rect)) {
					furb.isCollidingWithGlass = true;
					if (furb.canHit) {
						furb.canHit = false;
						gla.health--;
						playRandomGlassPanelHitSound(10);
						HF.Score += 2;// testing score (remove this!)
					}
				}
			}
			if (glassBottomRight.health > 0 && furb.rect.overlaps(glassBottomRight.rect)) {
				furb.isCollidingWithGlass = true;
				if (furb.canHit) {
					furb.canHit = false;
					glassBottomRight.health--;
					playRandomGlassPanelHitSound(10);
					HF.Score += 2;// testing score (remove this!)
				}
			}
			if (glassBottomLeft.health > 0 && furb.rect.overlaps(glassBottomLeft.rect)) {
				furb.isCollidingWithGlass = true;
				if (furb.canHit) {
					furb.canHit = false;
					glassBottomLeft.health--;
					playRandomGlassPanelHitSound(10);
					HF.Score += 2;// testing score (remove this!)
				}
			}
			if (glassUpperLeft.health > 0 && furb.rect.overlaps(glassUpperLeft.rect)) {
				furb.isCollidingWithGlass = true;
				if (furb.canHit) {
					furb.canHit = false;
					glassUpperLeft.health--;
					playRandomGlassPanelHitSound(10);
					HF.Score += 2;// testing score (remove this!)
				}
			}
			if (glassUpperRight.health > 0 && furb.rect.overlaps(glassUpperRight.rect)) {
				if (furb.canHit) {
					furb.canHit = false;
					glassUpperRight.health--;
					playRandomGlassPanelHitSound(10);
					HF.Score += 2;// testing score (remove this!)
				}
			}
			// bullet collisions with Furbals
			for (Iterator<Bullet> iter6 = bullets.iterator(); iter6.hasNext();) {
				Bullet bla = iter6.next();
				if (furb.rect.overlaps(bla.rect)) {
					furb.isDying = true;
					bla.isDead = true;
					HF.Score += 1;
				}
			}
			for (Iterator<Bullet> iter7 = bullets2.iterator(); iter7.hasNext();) {
				Bullet bla = iter7.next();
				if (furb.rect.overlaps(bla.rect)) {
					furb.isDying = true;
					bla.isDead = true;
					HF.Score += 1;
				}
			}
			if (HF.Health > 0 && furb.rect.overlaps(player.rect)) {
				if (!furb.isDying) {// now it only hits you once and sounds once. and negives your score once. i'll make it bigger tough. minus 20!
					HF.Health--;
					if (!Global.SetVolumeToZero)
						player.playRandomHurtSound(6);
					HF.Score -= 20;// testing score (remove this!)
				}
				furb.isDying = true;
			}
		}
	}

	public void checkBulletsCollisionsWithGlass(Array<Bullet> projectiles) {
		float vol = .1f;
		for (Iterator<Bullet> iter = projectiles.iterator(); iter.hasNext();) {
			Bullet projectile = iter.next();
			for (Iterator<Glass> iter2 = glassTop.iterator(); iter2.hasNext();) {
				Glass gla = iter2.next();
				if (gla.health > 0 && projectile.rect.overlaps(gla.rect)) {
					if (gla.health < 11)
						gla.health++;
					projectile.isDead = true;
					if (!Global.SetVolumeToZero)
						hit.play(vol);
				}
			}

			for (Iterator<Glass> iter3 = glassBottom.iterator(); iter3.hasNext();) {
				Glass gla = iter3.next();
				if (gla.health > 0 && projectile.rect.overlaps(gla.rect)) {
					if (gla.health < 11)
						gla.health++;
					projectile.isDead = true;
					if (!Global.SetVolumeToZero)
						hit.play(vol);
				}
			}
			for (Iterator<Glass> iter4 = glassLeft.iterator(); iter4.hasNext();) {
				Glass gla = iter4.next();
				if (gla.health > 0 && projectile.rect.overlaps(gla.rect)) {
					if (gla.health < 11)
						gla.health++;
					projectile.isDead = true;
					if (!Global.SetVolumeToZero)
						hit.play(vol);
				}
			}
			for (Iterator<Glass> iter5 = glassRight.iterator(); iter5.hasNext();) {
				Glass gla = iter5.next();
				if (gla.health > 0 && projectile.rect.overlaps(gla.rect)) {
					if (gla.health < 11)
						gla.health++;
					projectile.isDead = true;
					if (!Global.SetVolumeToZero)
						hit.play(vol);
				}
			}
			if (glassBottomRight.health > 0 && projectile.rect.overlaps(glassBottomRight.rect)) {
				if (glassBottomRight.health < 11)
					glassBottomRight.health++;
				projectile.isDead = true;
				if (!Global.SetVolumeToZero)
					hit.play(vol);
			}
			if (glassBottomLeft.health > 0 && projectile.rect.overlaps(glassBottomLeft.rect)) {
				if (glassBottomLeft.health < 11)
					glassBottomLeft.health++;
				projectile.isDead = true;
				if (!Global.SetVolumeToZero)
					hit.play(vol);
			}
			if (glassUpperLeft.health > 0 && projectile.rect.overlaps(glassUpperLeft.rect)) {
				if (glassUpperLeft.health < 11)
					glassUpperLeft.health++;
				projectile.isDead = true;
				if (!Global.SetVolumeToZero)
					hit.play(vol);
			}
			if (glassUpperRight.health > 0 && projectile.rect.overlaps(glassUpperRight.rect)) {
				if (glassUpperRight.health < 11)
					glassUpperRight.health++;
				projectile.isDead = true;
				if (!Global.SetVolumeToZero)
					hit.play(vol);
			}
		}
	}

	public void playRandomGlassPanelHitSound(int numberOfSounds) {
		int randomSound = MathUtils.random(1, numberOfSounds);
		if (!Global.SetVolumeToZero) {
			if (randomSound == 1)
				glassPaneHit.play();
			else if (randomSound == 2)
				glassPaneHit2.play();
			else if (randomSound == 3)
				glassPaneHit3.play();
			else if (randomSound == 4)
				glassPaneHit4.play();
			else if (randomSound == 5)
				glassPaneHit5.play();
			else if (randomSound == 6)
				glassPaneHit6.play();
			else if (randomSound == 7)
				glassPaneHit7.play();
			else if (randomSound == 8)
				glassPaneHit8.play();
			else if (randomSound == 9)
				glassPaneHit9.play();
			else if (randomSound == 10)
				glassPaneHit10.play();
		}
	}

	@Override
	public void dispose() {
		// dropSound.dispose();
		// calm.dispose();
		// sfx_growl.dispose();
		// growlHit.dispose();
		enter.dispose();
		enter2.dispose();
		levelMusic.dispose();
		hit.dispose();
		player.dispose();// for disposing the sound effects... because i'm not sure what needs disposed yet. I don't even know if this is needed. lol
		glassPaneHit.dispose();
		glassPaneHit2.dispose();
		glassPaneHit3.dispose();
		glassPaneHit4.dispose();
		glassPaneHit5.dispose();
		glassPaneHit6.dispose();
		glassPaneHit7.dispose();
		glassPaneHit8.dispose();
		glassPaneHit9.dispose();
		glassPaneHit10.dispose();
		death.dispose();
	}

	@Override
	public void resize(int width, int height) {
		vport.update(width, height, true);
	}

	@Override
	public void hide() {
		// rainMusic.stop();
	}

	@Override
	public void pause() {
	}

	@Override
	public void resume() {
	}

}
