import java.awt.Color;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;

import javax.imageio.ImageIO;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.swing.JFrame;

public class FryDay extends JFrame {
	
	public static final int mapWidth = 22;
	public static final int mapHeight = 18;
	
	public Player playerCharacter;
	public Enemy[] enemies;
	public MapPosition[][] map;
	
	public int startingPoint;
	
	public int difficulty = 0;
	
	public int gameState = 0;
	
	public ArrayList<Integer> upCharCodes;
	public ArrayList<Integer> downCharCodes;
	public ArrayList<Integer> leftCharCodes;
	public ArrayList<Integer> rightCharCodes;
	public ArrayList<Integer> forwardCodes;
	public ArrayList<Integer> backCodes;
	
	public long lastGameLoop;
	
	public boolean gotMug;
	public boolean gotJug;
	public boolean gotNewspaper;
	public boolean gotWater;
	public boolean gotCoffee;
	public boolean fuseRunning;
	
	int hallwayWidth;
	int hallwayLeft;
	
	int wallLeftOffices;
	int wallRightOffices;
	int doorLeftUp;
	int doorRightUp;
	int doorLeftDown;
	int doorRightDown;
	
	BufferedImage wall1Picture;
	BufferedImage wall2Picture;
	BufferedImage wall3Picture;
	BufferedImage wallUpPicture;
	BufferedImage playerPicture;
	BufferedImage enemyPicture;
	BufferedImage fusePicture;
	BufferedImage mugPicture;
	BufferedImage jugPicture;
	BufferedImage desk1Picture;
	BufferedImage desk2Picture;
	BufferedImage desk3Picture;
	BufferedImage desk4Picture;
	BufferedImage ownDeskPicture;
	BufferedImage coffeeMachinePicture;
	BufferedImage newspaperPicture;
	BufferedImage waterPicture;
	BufferedImage carpetPicture;
	BufferedImage mainMenuPicture;
	BufferedImage lostScreenPicture;
	BufferedImage wonScreenPicture;
	
	Clip winningSound;
	Clip losingSound;
	Clip punchSound;
	Clip chatting1Sound;
	Clip chatting2Sound;
	Clip chatting3Sound;
	Clip pickupSound;
	Clip wrongNewspaperSound; 
	
	int xSize;
	int ySize;
	

	
	public static void main(String[] args) {
		new FryDay();
	}
	
	public FryDay()
	{
		try
		{
			playerPicture = ImageIO.read(new File("graphics/player.png"));
			enemyPicture = ImageIO.read(new File("graphics/enemy.png"));
			wall1Picture = ImageIO.read(new File("graphics/wall1.png"));
			wall2Picture = ImageIO.read(new File("graphics/wall2.png"));
			wall3Picture = ImageIO.read(new File("graphics/wall3.png"));
			wallUpPicture = ImageIO.read(new File("graphics/wallUp.png"));
			fusePicture = ImageIO.read(new File("graphics/fuse.png"));
			mugPicture = ImageIO.read(new File("graphics/mug.png"));
			jugPicture = ImageIO.read(new File("graphics/jug.png"));
			desk1Picture = ImageIO.read(new File("graphics/desk1.png"));
			desk2Picture = ImageIO.read(new File("graphics/desk2.png"));
			desk3Picture = ImageIO.read(new File("graphics/desk3.png"));
			desk4Picture = ImageIO.read(new File("graphics/desk4.png"));
			ownDeskPicture = ImageIO.read(new File("graphics/owndesk.png"));
			coffeeMachinePicture = ImageIO.read(new File("graphics/coffeemachine.png"));
			newspaperPicture = ImageIO.read(new File("graphics/newspaper.png"));
			waterPicture = ImageIO.read(new File("graphics/waterDispenser.png"));
			carpetPicture = ImageIO.read(new File("graphics/carpet.png"));
			mainMenuPicture = ImageIO.read(new File("graphics/mainMenu.png"));
			lostScreenPicture = ImageIO.read(new File("graphics/lostScreen.png"));
			wonScreenPicture = ImageIO.read(new File("graphics/wonScreen.png"));
			
			AudioInputStream  stream = AudioSystem.getAudioInputStream(new File("sounds/chatting1.wav"));
			DataLine.Info info = new DataLine.Info(Clip.class, stream.getFormat());
			chatting1Sound = (Clip) AudioSystem.getLine(info);
			chatting1Sound.open(stream);

			stream = AudioSystem.getAudioInputStream(new File("sounds/chatting2.wav"));
			chatting2Sound = (Clip) AudioSystem.getLine(info);
			chatting2Sound.open(stream);

			stream = AudioSystem.getAudioInputStream(new File("sounds/chatting3.wav"));
			chatting3Sound = (Clip) AudioSystem.getLine(info);
			chatting3Sound.open(stream);

			stream = AudioSystem.getAudioInputStream(new File("sounds/stopEnemy.wav"));
			punchSound = (Clip) AudioSystem.getLine(info);
			punchSound.open(stream);

			stream = AudioSystem.getAudioInputStream(new File("sounds/losingSound.wav"));
			losingSound = (Clip) AudioSystem.getLine(info);
			losingSound.open(stream);

			stream = AudioSystem.getAudioInputStream(new File("sounds/winSound.wav"));
			winningSound = (Clip) AudioSystem.getLine(info);
			winningSound.open(stream);

			stream = AudioSystem.getAudioInputStream(new File("sounds/pickupSound.wav"));
			pickupSound = (Clip) AudioSystem.getLine(info);
			pickupSound.open(stream);

			stream = AudioSystem.getAudioInputStream(new File("sounds/wrongNewspaper.wav"));
			wrongNewspaperSound = (Clip) AudioSystem.getLine(info);
			wrongNewspaperSound.open(stream);

		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
		
		upCharCodes = new ArrayList<Integer>();
		upCharCodes.add(KeyEvent.VK_UP);
		upCharCodes.add(KeyEvent.VK_W);
		
		downCharCodes = new ArrayList<Integer>();
		downCharCodes.add(KeyEvent.VK_DOWN);
		downCharCodes.add(KeyEvent.VK_S);
		
		leftCharCodes = new ArrayList<Integer>();
		leftCharCodes.add(KeyEvent.VK_LEFT);
		leftCharCodes.add(KeyEvent.VK_A);
		
		rightCharCodes = new ArrayList<Integer>();
		rightCharCodes.add(KeyEvent.VK_RIGHT);
		rightCharCodes.add(KeyEvent.VK_D);

		forwardCodes = new ArrayList<Integer>();
		forwardCodes.add(KeyEvent.VK_ENTER);

		backCodes = new ArrayList<Integer>();
		backCodes.add(KeyEvent.VK_ESCAPE);

		
		Toolkit tk = Toolkit.getDefaultToolkit();
		xSize = ((int) tk.getScreenSize().getWidth());
		ySize = ((int) tk.getScreenSize().getHeight());
		
		setBounds(0, 0, xSize, ySize);
		setResizable(false);
		setLayout(null);
		setUndecorated(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		map = new MapPosition[mapWidth][mapHeight];
		playerCharacter = new Player();
		initializeMap();
		difficulty = 60;
		
		setMapForDifficulty();
		
		addKeyListener(new KeyListener() {
			
			@Override
			public void keyTyped(KeyEvent e) {
				reactToButtonRelease(e.getKeyCode());
			}
			
			@Override
			public void keyReleased(KeyEvent e) {
				reactToButtonRelease(e.getKeyCode());
			}
			
			@Override
			public void keyPressed(KeyEvent e) {
				reactToButtonPressed(e.getKeyCode());
			}
		});
		
		setVisible(true);
	}
	
	public void reactToButtonPressed(int charCode)
	{
		if(gameState == 1)
		{
			if(upCharCodes.contains(charCode))
			{
				playerCharacter.headingUp = true;
			}
			if(downCharCodes.contains(charCode))
			{
				playerCharacter.headingDown = true;
			}
			if(leftCharCodes.contains(charCode))
			{
				playerCharacter.headingLeft = true;
			}
			if(rightCharCodes.contains(charCode))
			{
				playerCharacter.headingRight = true;
			}
		}
	}

	public void reactToButtonRelease(int charCode)
	{
		if(gameState == 0)
		{
			if(upCharCodes.contains(charCode))
			{
				initializeMap();
				setMapForDifficulty();
			}
			else if(forwardCodes.contains(charCode))
			{
				difficulty = 0;
				playerCharacter.annoyance = 0;
				setMapForDifficulty();
				gameState = 1;
			}
			else if(backCodes.contains(charCode))
			{
				System.exit(0);
			}
		}
		else if(gameState == 1)
		{
			if(upCharCodes.contains(charCode))
			{
				playerCharacter.headingUp = false;
			}
			if(downCharCodes.contains(charCode))
			{
				playerCharacter.headingDown = false;
			}
			if(leftCharCodes.contains(charCode))
			{
				playerCharacter.headingLeft = false;
			}
			if(rightCharCodes.contains(charCode))
			{
				playerCharacter.headingRight = false;
			}
			else if(backCodes.contains(charCode))
			{
				gameState = 0;
			}
		}
		if(gameState == 2)
		{
			if(forwardCodes.contains(charCode))
			{
				difficulty++;
				setMapForDifficulty();
				gameState = 1;
			}
			else if(backCodes.contains(charCode))
			{
				difficulty = 60;
				initializeMap();
				setMapForDifficulty();
				gameState = 0;
			}
		}
		if(gameState == 3)
		{
			if(forwardCodes.contains(charCode))
			{
				difficulty = 60;
				setMapForDifficulty();
				gameState = 0;
			}
			else if(backCodes.contains(charCode))
			{
				difficulty = 60;
				setMapForDifficulty();
				gameState = 0;
			}
		}
	}

	
	private void initializeMap()
	{
		for(int i = 0; i < mapWidth; i++)
		{
			for(int j = 0; j < mapHeight; j++)
			{
				map[i][j] = new MapPosition();
				map[i][j].coffeeJug = false;
				map[i][j].coffeeMachine = false;
				map[i][j].coffeeMug = false;
				map[i][j].fuse = false;
				map[i][j].newspaper = false;
				map[i][j].waterDispenser = false;
				map[i][j].wrongNewspaper = false;
				map[i][j].wall = false;
				map[i][j].desk = false;
				map[i][j].ownDesk = false;
			}
		}
		
		for(int i = 0; i < mapWidth; i++)
		{
			map[i][0].wall = true;
			map[i][mapHeight - 1].wall = true;
		}
		
		for(int j = 0; j < mapHeight; j++)
		{
			map[0][j].wall = true;
			map[mapWidth - 1][j].wall = true;
		}
		
		hallwayWidth = (int)(Math.random() * 3 + 1);
		hallwayLeft = (int)(Math.random() * (mapWidth - hallwayWidth - 2) + 5);
		
		while(hallwayWidth + hallwayLeft > mapWidth - 9)
		{
			hallwayLeft--;
		}
		
		wallLeftOffices = (int)(Math.random() * mapHeight * 8 / 10 + 2);
		wallRightOffices = (int)(Math.random() * mapHeight * 8 / 10 + 2);
		doorLeftUp = (int)(Math.random() * wallLeftOffices);
		doorRightUp = (int)(Math.random() * wallRightOffices);
		doorLeftDown = wallLeftOffices + (int)(Math.random() * (mapHeight - wallLeftOffices - 1)) + 1;
		doorRightDown = wallRightOffices + (int)(Math.random() * (mapHeight - wallRightOffices - 1)) + 1;

		while(wallLeftOffices <= 4)
		{
			wallLeftOffices++;
			doorLeftDown++;
		}
		while(wallLeftOffices > mapHeight - 5)
		{
			wallLeftOffices--;
			doorLeftUp--;
		}
		while(wallRightOffices <= 4)
		{
			wallRightOffices++;
			doorRightDown++;
		}
		while(wallRightOffices > mapHeight - 5)
		{
			wallRightOffices--;
			doorRightUp--;
		}
		while(doorLeftUp <= 1)
		{
			doorLeftUp++;
		}
		while(doorLeftDown > mapHeight - 2)
		{
			doorLeftDown--;
		}
		while(doorRightUp <= 1)
		{
			doorRightUp++;
		}
		while(doorRightDown >= mapHeight - 2)
		{
			doorRightDown--;
		}
		
		for(int j = 0; j < mapHeight; j++)
		{
			map[hallwayLeft][j].wall = true;
			map[hallwayLeft + hallwayWidth + 2][j].wall = true;
		}

		
		for(int i = 0; i < hallwayLeft; i++)
		{
			map[i][wallLeftOffices].wall = true;
		}
		for(int i = hallwayLeft + hallwayWidth + 2; i < mapWidth; i++)
		{
			map[i][wallRightOffices].wall = true;
		}
		
		map[hallwayLeft][doorLeftUp].wall = false;
		map[hallwayLeft][doorLeftDown].wall = false;
		map[hallwayLeft + hallwayWidth + 2][doorRightUp].wall = false;
		map[hallwayLeft + hallwayWidth + 2][doorRightDown].wall = false;
		
		startingPoint = hallwayLeft + hallwayWidth / 2 + 1;
		
		for(int i = 0; i < mapHeight; i++)
		{
			if(map[1][i].wall == false)
			{
				map[1][i].desk = true;
			}
			if(map[mapWidth - 2][i].wall == false)
			{
				map[mapWidth - 2][i].desk = true;
			}
			
			if(i != doorLeftUp && i != doorLeftDown)
			{
				if(map[hallwayLeft - 1][i].wall == false)
				{
					map[hallwayLeft - 1][i].desk = true;
				}
				if(map[hallwayLeft - 1][i].wall == false)
				{
					map[hallwayLeft - 1][i].desk = true;
				}
			}
			
			if(i != doorRightDown && i != doorRightUp)
			{
				if(map[hallwayLeft + hallwayWidth + 3][i].wall == false)
				{
					map[hallwayLeft + hallwayWidth + 3][i].desk = true;
				}
				if(map[hallwayLeft + hallwayWidth + 3][i].wall == false)
				{
					map[hallwayLeft + hallwayWidth + 3][i].desk = true;
				}
			}
		}
		
		
		placeCoffeemachine();
		placeWaterDispenser();
		placeFuse();
		placeOwnDesk();
	}

	private void placeCoffeemachine() {
		ArrayList<MapPosition> validPositions;
		validPositions = new ArrayList<MapPosition>();
		for(int i = 3; i < hallwayLeft - 2; i++)
		{
			if(doorLeftUp != 1)
			{
				validPositions.add(map[i][1]);
			}
			if(doorLeftDown != mapHeight - 2)
			{
				validPositions.add(map[i][mapHeight - 2]);
			}
			if(doorLeftUp != wallLeftOffices - 1)
			{
				validPositions.add(map[i][wallLeftOffices - 1]);
			}
			if(doorLeftDown != wallLeftOffices + 1)
			{
				validPositions.add(map[i][wallLeftOffices + 1]);
			}
		}

		for(int i = hallwayLeft + hallwayWidth + 5; i < mapWidth - 3; i++)
		{
			if(doorRightUp != 1)
			{
				validPositions.add(map[i][1]);
			}
			if(doorRightDown != mapHeight - 2)
			{
				validPositions.add(map[i][mapHeight - 2]);
			}
			if(doorRightUp != wallRightOffices - 1)
			{
				validPositions.add(map[i][wallRightOffices - 1]);
			}
			if(doorRightDown != wallRightOffices + 1)
			{
				validPositions.add(map[i][wallRightOffices + 1]);
			}
		}
		
		for(int i = 0; i < validPositions.size(); i++)
		{
			if(validPositions.get(i).fuse == true || validPositions.get(i).waterDispenser)
			{
				validPositions.remove(i);
			}
		}
		
		
		int pickedPosition = (int)(Math.random() * validPositions.size());
		validPositions.get(pickedPosition).coffeeMachine = true;
	}
	
	private void placeWaterDispenser() {
		ArrayList<MapPosition> validPositions;
		validPositions = new ArrayList<MapPosition>();
		for(int i = 3; i < hallwayLeft - 2; i++)
		{
			for(int j = 1; j < mapHeight - 1; j++)
			{
				
				if(j != doorLeftDown && j != doorLeftUp && 
						map[i][j].coffeeMachine == false && map[i][j].desk == false && map[i][j].wall == false)
				{
					validPositions.add(map[i][j]);
				}
			}
		}

		for(int i = hallwayLeft + hallwayWidth + 5; i < mapWidth - 3; i++)
		{
			for(int j = 1; j < mapHeight - 1; j++)
			{
				if(j != doorRightDown && j != doorRightUp &&  map[i][j].coffeeMachine == false && map[i][j].desk == false && map[i][j].wall == false)
				{
					validPositions.add(map[i][j]);
				}
			}
		}

		
		
		int pickedPosition = (int)(Math.random() * validPositions.size());
		validPositions.get(pickedPosition).waterDispenser = true;
	}
	
	private void placeFuse() {
		ArrayList<MapPosition> validPositions;
		validPositions = new ArrayList<MapPosition>();
		for(int j = 1; j < mapHeight - 3; j++)
		{
			if(j != doorLeftDown && j != doorLeftUp && j != doorRightDown & j != doorRightUp)
			{
				validPositions.add(map[hallwayLeft + 1][j]);
				validPositions.add(map[hallwayLeft + hallwayWidth + 1][j]);
			}
		}
		
		int pickedPosition = (int)(Math.random() * validPositions.size());
		validPositions.get(pickedPosition).fuse = true;
	}
	
	private void placeOwnDesk()
	{
		MapPosition pickedDesk = findEmptyDesk();
		pickedDesk.ownDesk = true;
	}

	private MapPosition findEmptyDesk() {
		ArrayList<MapPosition> validPositions;
		validPositions = new ArrayList<MapPosition>();

		for(int i = 1; i < mapWidth - 1; i++)
		{
			for(int j = 1; j < mapHeight - 1; j++)
			{
				if(map[i][j].desk == true && map[i][j].ownDesk == false && map[i][j].newspaper == false && map[i][j].wrongNewspaper == false)
				{
					if(map[i+1][j].waterDispenser == false && map[i+1][j].coffeeMachine == false
							&& map[i-1][j].waterDispenser == false && map[i-1][j].coffeeMachine == false
									&& map[i][j+1].waterDispenser == false && map[i][j+1].coffeeMachine == false
											&& map[i][j-1].waterDispenser == false && map[i][j-1].coffeeMachine == false)
					{
						validPositions.add(map[i][j]);
					}
				}
			}
		}
		int pickedPosition = (int)(Math.random() * validPositions.size());
		MapPosition pickedDesk = validPositions.get(pickedPosition);
		return pickedDesk;
	}
	
	
	private void setMapForDifficulty()
	{
		int newAnnoyance = (int)(playerCharacter.annoyance * (difficulty / 100f));
	
		
		for(int i = 0; i < mapWidth; i++)
		{
			for(int j = 0; j < mapHeight; j++)
			{
				map[i][j].coffeeJug = false;
				map[i][j].coffeeMug = false;
				map[i][j].newspaper = false;
				map[i][j].wrongNewspaper = false;
			}
		}
		
		playerCharacter = new Player();
		playerCharacter.annoyance = newAnnoyance;
		playerCharacter.x = startingPoint;
		playerCharacter.y = mapHeight - 2;
		
		gotCoffee = false;
		gotNewspaper = false;
		gotJug = true;
		gotMug = true;
		gotWater = true;
		fuseRunning = true;
		
		MapPosition properNewspaper= findEmptyDesk();
		properNewspaper.newspaper = true;
		int difficultyLeft = difficulty;
		
		
		int oneTimeRandomDifficulty = (int)(Math.random() * 3);
		if((oneTimeRandomDifficulty == 0 && difficultyLeft > 0) || difficulty > 3)
		{
			gotMug = false;
			MapPosition mugDesk = findEmptyDesk();
			mugDesk.coffeeMug = true;
			difficultyLeft--;
		}
		
		oneTimeRandomDifficulty = (int)(Math.random() * 3);
		if((oneTimeRandomDifficulty == 0 && difficultyLeft > 0) || difficulty > 6)
		{
			gotJug = false;
			MapPosition jugDesk = findEmptyDesk();
			jugDesk.coffeeJug = true;
			difficultyLeft--;
		}
		
		oneTimeRandomDifficulty = (int)(Math.random() * 4);
		if(oneTimeRandomDifficulty == 0 && difficultyLeft > 0 && (gotJug == true && gotMug == true))
		{
			gotMug = false;
			MapPosition mugDesk = findEmptyDesk();
			mugDesk.coffeeMug = true;
			gotJug = false;
			MapPosition jugDesk = findEmptyDesk();
			jugDesk.coffeeJug = true;
			difficultyLeft--;
		}
		
		oneTimeRandomDifficulty = (int)(Math.random() * 5);
		if((oneTimeRandomDifficulty == 0 && difficultyLeft > 0) || difficulty > 9)
		{
			fuseRunning = false;
			difficultyLeft--;
		}
		
		oneTimeRandomDifficulty = (int)(Math.random() * 10);
		if(oneTimeRandomDifficulty == 0 && difficultyLeft > 0)
		{
			for(int i = 1; i < mapWidth - 1; i++)
			{
				for(int j = 1; j < mapHeight - 1; j++)
				{
					map[i][j].ownDesk = false;
				}
			}
			placeOwnDesk();
			difficultyLeft--;
		}
		
		oneTimeRandomDifficulty = (int)(Math.random() * 10);
		if(oneTimeRandomDifficulty == 0 && difficultyLeft > 0)
		{
			for(int i = 1; i < mapWidth - 1; i++)
			{
				for(int j = 1; j < mapHeight - 1; j++)
				{
					map[i][j].coffeeMachine = false;
				}
			}

			placeCoffeemachine();
			difficultyLeft--;
		}

		oneTimeRandomDifficulty = (int)(Math.random() * 10);
		if(oneTimeRandomDifficulty == 0 && difficultyLeft > 0)
		{
			for(int i = 1; i < mapWidth - 1; i++)
			{
				for(int j = 1; j < mapHeight - 1; j++)
				{
					map[i][j].waterDispenser = false;
				}
			}

			placeWaterDispenser();
			difficultyLeft--;
		}
		
		oneTimeRandomDifficulty = (int)(Math.random() * 20);
		if(oneTimeRandomDifficulty == 0 && difficultyLeft > 0)
		{
			for(int i = 1; i < mapWidth - 1; i++)
			{
				for(int j = 1; j < mapHeight - 1; j++)
				{
					map[i][j].ownDesk = false;
					map[i][j].fuse = false;
					map[i][j].coffeeMachine = false;
					map[i][j].waterDispenser = false;
				}
			}

			placeFuse();
			placeOwnDesk();
			placeWaterDispenser();
			placeCoffeemachine();
			difficultyLeft--;
		}
		
		oneTimeRandomDifficulty = (int)(Math.random() * 2);
		if((oneTimeRandomDifficulty == 0 && difficultyLeft > 0) || difficulty > 12)
		{
			difficultyLeft--;
			gotWater = false;
		}
		
		oneTimeRandomDifficulty = (int)(Math.random() * 20);
		if(difficulty % 10 == 9 || oneTimeRandomDifficulty == 0)
		{
			difficulty++;
			difficultyLeft--;
			initializeMap();
			setMapForDifficulty();
		}


		int enemyAmount = 1;
		int enemySpeedups = 0;
		int playerSlowdowns = 0;
		int fakeNewspapers = 0;
		
		while(difficultyLeft > 0)
		{
			int muplieDifficultyRandom = (int)(Math.random() * 11);
			if(muplieDifficultyRandom < 4)
			{
				enemyAmount++;
				difficultyLeft--;
			}
			else if(muplieDifficultyRandom >= 4 && muplieDifficultyRandom < 7)
			{
				enemySpeedups++;
				difficultyLeft--;
			}
			else if(muplieDifficultyRandom == 8)
			{
				playerSlowdowns++;
				difficultyLeft--;
			}
			else
			{
				fakeNewspapers++;
				difficultyLeft--;
			}
		}
		
		while(playerSlowdowns > 0)
		{
			playerCharacter.movmentSpeed += 50;
			playerSlowdowns--;
		}
		
		while(fakeNewspapers > 0)
		{
			findEmptyDesk().wrongNewspaper = true;
			fakeNewspapers--;
		}
		
		enemies = new Enemy[enemyAmount];
		for(int i = 0; i < enemyAmount; i++)
		{
			enemies[i] = new Enemy();
			boolean foundSpot = false;
			int xRandom = 3;
			int yRandom = 3;
			while(!foundSpot)
			{
				xRandom = (int)(Math.random() * mapWidth - 2 + 1);
				yRandom = (int)(Math.random() * mapHeight - 2 + 1);
				if(map[xRandom][yRandom].isEmty() && checkForOccupant(xRandom, yRandom) == null)
				{
					foundSpot = true;
				}
			}
			enemies[i].x = xRandom;
			enemies[i].y = yRandom;
			enemies[i].movementCooldown = xRandom + yRandom;
		}
		
		int tries = 0;
		while(enemySpeedups > 0 && tries < 100)
		{
			int enemySpeedUp = (int)(Math.random() * enemyAmount);
			if(enemies[enemySpeedUp].movmentSpeed >= 100)
			{
				enemies[enemySpeedUp].movmentSpeed -= 25;
				
				enemySpeedups--;
			}
			else
			{
				tries++;
			}
		}
	}
	
	private void moveActor(Actor actor, int deltaTime)
	{
		actor.movementCooldown = actor.movementCooldown - deltaTime;
		
		if(actor.movementCooldown <= 0)
		{
			boolean moving = false;
			int newX = actor.x;
			int newY = actor.y;
			if(actor.headingDown)
			{
				newX = actor.x;
				newY = actor.y + 1;
			}
			else if(actor.headingUp)
			{
				newX = actor.x;
				newY = actor.y - 1;
			}
			else if(actor.headingLeft)
			{
				newX = actor.x - 1;
				newY = actor.y;
			}
			else if(actor.headingRight)
			{
				newX = actor.x + 1;
				newY = actor.y;
			}
			if(actor.x != newX || actor.y != newY)
			{
				moveOrderToNewSquare(actor, moving, newX, newY);				
			}
		}
	}

	private void moveOrderToNewSquare(Actor actor, boolean moving, int newX, int newY) {
		if(actor == playerCharacter)
		{
			if(!map[newX][newY].isEmty())
			{
				if(map[newX][newY].newspaper == true)
				{
					map[newX][newY].newspaper = false;
					gotNewspaper = true;
					pickupSound.setFramePosition(0);
					pickupSound.start();
				}
				else if(map[newX][newY].wrongNewspaper == true)
				{
					map[newX][newY].wrongNewspaper = false;
					wrongNewspaperSound.setFramePosition(0);
					wrongNewspaperSound.start();

				}
				else if(map[newX][newY].coffeeJug == true)
				{
					map[newX][newY].coffeeJug = false;
					gotJug = true;
					pickupSound.setFramePosition(0);
					pickupSound.start();

				}
				else if(map[newX][newY].coffeeMug == true)
				{
					map[newX][newY].coffeeMug = false;
					gotMug = true;
					pickupSound.setFramePosition(0);
					pickupSound.start();

				}
				else if(map[newX][newY].waterDispenser == true && gotJug)
				{
					gotWater = true;
					pickupSound.setFramePosition(0);
					pickupSound.start();

				}
				else if(map[newX][newY].fuse == true && fuseRunning == false)
				{
					fuseRunning = true;
					pickupSound.setFramePosition(0);
					pickupSound.start();

				}
				else if(map[newX][newY].coffeeMachine == true && gotJug && gotMug && gotWater && fuseRunning && !gotCoffee)
				{
					gotCoffee = true;
					pickupSound.setFramePosition(0);
					pickupSound.start();

				}
				else if(map[newX][newY].ownDesk == true && gotCoffee && gotNewspaper)
				{
					winningSound.setFramePosition(0);
					winningSound.start();
					gameState = 2;
				}
			}
		}
		
		if(map[newX][newY].isEmty())
		{
			Actor occpant = checkForOccupant(newX,  newY);
			if(occpant == null)
			{
				actor.x = newX;
				actor.y = newY;

	 			actor.movementCooldown = actor.movmentSpeed;
			}
			else
			{
				
				if(actor == playerCharacter)
				{
					punchSound.setFramePosition(0);
					punchSound.start();
					
					occpant.headingDown = actor.headingDown;
					occpant.headingUp = actor.headingUp;
					occpant.headingLeft = actor.headingLeft;
					occpant.headingRight = actor.headingRight;
					occpant.movmentSpeed -= 5;
					
					
					playerCharacter.annoyance -= 25;
					if(playerCharacter.annoyance < 0)
					{
						playerCharacter.annoyance = 0;
					}
					actor.movementCooldown += actor.movmentSpeed / 2;
				}
				else
				{
					if(occpant == playerCharacter)
					{
						playerCharacter.annoyance += 25;
						if(playerCharacter.annoyance > 999)
						{
							playerCharacter.annoyance = 999;
						}
					}
					occpant.movementCooldown += actor.movmentSpeed;
					actor.movementCooldown += actor.movmentSpeed / 4;
					
					if(gameState == 1)
					{
						if((chatting1Sound.getFramePosition() > chatting1Sound.getFrameLength() / 2) || !chatting1Sound.isRunning())
						{
							chatting1Sound.setFramePosition(0);
							chatting1Sound.start();
						}
						else if((chatting1Sound.getFramePosition() > chatting1Sound.getFrameLength() / 4) && ((chatting2Sound.getFramePosition() > chatting2Sound.getFrameLength() / 2) || !chatting2Sound.isRunning()))
						{
							chatting2Sound.setFramePosition(0);
							chatting2Sound.start();
						}
						else if((chatting2Sound.getFramePosition() > chatting2Sound.getFrameLength() / 4) && ((chatting3Sound.getFramePosition() > chatting3Sound.getFrameLength() / 2) || !chatting3Sound.isRunning()))
						{
							chatting3Sound.setFramePosition(0);
							chatting3Sound.start();
						}
					}
				}
			}
		}
		else
		{
			actor.headingUp = false;
			actor.headingDown = false;
			actor.headingLeft = false;
			actor.headingRight = false;
		}
	}
	
	private Actor checkForOccupant(int x, int y)
	{
		if(playerCharacter.x == x && playerCharacter.y == y)
		{
			return playerCharacter;
		}
		for(int i = 0; i < enemies.length; i++)
		{
			if(enemies[i] != null && enemies[i].x == x && enemies[i].y == y)
			{
				return enemies[i];
			}
		}
		
		return null;
	}
	
	private void checkEnemyMovement(Enemy enemy)
	{
		int changeDirection = (int)(Math.random() * 4);
		if(changeDirection == 0)
		{
			enemy.headingDown = false;
			enemy.headingUp = false;
			enemy.headingLeft = false;
			enemy.headingRight = false;
		}
		if(enemy.headingDown == false && enemy.headingUp == false && enemy.headingLeft == false && enemy.headingRight == false)
		{
			int newDirection = (int)(Math.random() * 6);
			if(newDirection == 0)
			{
				enemy.headingRight = true;
			}
			else if(newDirection == 1)
			{
				enemy.headingLeft = true;
			}
			else if(newDirection == 2)
			{
				enemy.headingUp = true;
			}
			else if(newDirection == 3)
			{
				enemy.headingDown = true;
			}
		}
	}
	
	private void doGameLogic()
	{
		long now = new Date().getTime();
		int deltaTime = (int)(now - lastGameLoop);
				
		if(deltaTime > 1000)
		{
			deltaTime = 1000;
		}
		else if(deltaTime < 0)
		{
			deltaTime = 0;
		}

		if(gameState == 1)
		{
			playerCharacter.annoyance += deltaTime / 100;
			if(playerCharacter.annoyance >= 1000)
			{
				losingSound.setFramePosition(0);
				losingSound.start();
				gameState = 3;
			}
			
			moveActor(playerCharacter, deltaTime);
		}
		
		for(int i = 0; i < enemies.length; i++)
		{
			moveActor(enemies[i], deltaTime);
			checkEnemyMovement(enemies[i]);
		}

		lastGameLoop = now;
	}
	
	@Override
	public void paint(Graphics g2)
	{
//		super.paint(g);
		doGameLogic();
		
		BufferedImage newImage = new BufferedImage(1000, 850, BufferedImage.TYPE_INT_RGB);
		Graphics g = newImage.getGraphics();
		
		g.setColor(new Color(playerCharacter.annoyance / 1000f, 0.1f, 0.1f));
		g.fillRect(0, 0, 1000, 850);
		
		for(int i = 0; i < 5; i++)
		{
			for(int j = 0; j < 4; j++)
			{
				g.drawImage(carpetPicture, (i) * 200, (j) * 200, null);
			}
		}
		
		for(int i = 1; i < mapWidth - 1; i++)
		{
			for(int j = 1; j < mapHeight - 1; j++)
			{
				if(map[i][j].wall == true)
				{
					if(map[i][j+1].wall == true)
					{
						g.drawImage(wallUpPicture, (i - 1) * 50, (j-1) * 50, null);
					}
					else
					{
						if((i+j)% 5 == 0)
						{
							g.drawImage(wall3Picture, (i - 1) * 50, (j-1) * 50, null);
						}
						else if((i+j)% 5 == 3)
						{
							g.drawImage(wall2Picture, (i - 1) * 50, (j-1) * 50, null);
						}
						else
						{
							g.drawImage(wall1Picture, (i - 1) * 50, (j-1) * 50, null);
						}
					}
				}
				else if(map[i][j].desk == true)
				{
					if(map[i][j].ownDesk == true)
					{
						g.drawImage(ownDeskPicture, (i - 1) * 50, (j-1) * 50, null);
					}
					else
					{
						if((i*j)% 7 == 0)
						{
							g.drawImage(desk2Picture, (i - 1) * 50, (j-1) * 50, null);
						}
						else if((i*j)% 7 == 1)
						{
							g.drawImage(desk1Picture, (i - 1) * 50, (j-1) * 50, null);
						}
						else if((i*j)% 7 == 4 || (i*j)% 7 == 6)
						{
							g.drawImage(desk4Picture, (i - 1) * 50, (j-1) * 50, null);
						}
						else
						{
							g.drawImage(desk3Picture, (i - 1) * 50, (j-1) * 50, null);
						}
					}
				}
				
				if(map[i][j].newspaper || map[i][j].wrongNewspaper)
				{
					g.drawImage(newspaperPicture, (i - 1) * 50, (j-1) * 50, null);
				}
				if(map[i][j].coffeeJug)
				{
					g.drawImage(jugPicture, (i - 1) * 50, (j-1) * 50, null);
				}
				if(map[i][j].coffeeMug)
				{
					g.drawImage(mugPicture, (i - 1) * 50, (j-1) * 50, null);
				}
				if(map[i][j].waterDispenser)
				{
					g.drawImage(waterPicture, (i - 1) * 50, (j-1) * 50, null);
				}
				else if(map[i][j].fuse)
				{
					g.drawImage(fusePicture, (i - 1) * 50, (j-1) * 50, null);
				}
				if(map[i][j].coffeeMachine)
				{
					g.drawImage(coffeeMachinePicture, (i - 1) * 50, (j-1) * 50, null);
				}
			}
		}
		
		g.drawImage(playerPicture, (playerCharacter.x - 1) * 50, (playerCharacter.y - 1) * 50, null);
		for(int i = 0; i < enemies.length; i++)
		{
			g.drawImage(enemyPicture, (enemies[i].x - 1) * 50, (enemies[i].y - 1) * 50, null);
		}

		g.setColor(Color.BLACK);
		g.fillRect((int)(playerCharacter.annoyance / 1000f * 1000), 800, 1000 - (int)(playerCharacter.annoyance / 1000f * 1000), 50);

		
		Color brown = new Color(139,69,19);
		
		if(!fuseRunning)
		{
			g.setColor(Color.red);
		}
		else
		{
			g.setColor(brown);
		}
		g.fillOval(0, 800, 50, 50);
		if(!gotMug)
		{
			g.setColor(Color.red);
		}
		else
		{
			g.setColor(brown);
		}
		g.fillOval(50, 800, 50, 50);
		if(!gotJug)
		{
			g.setColor(Color.red);
		}
		else
		{
			g.setColor(brown);
		}
		g.fillOval(100, 800, 50, 50);
		if(!gotWater && !gotJug)
		{
			g.setColor(Color.gray);
		}
		else if(!gotWater)
		{
			g.setColor(Color.red);
		}
		else
		{
			g.setColor(brown);
		}
		g.fillOval(150, 800, 50, 50);
		if(!gotCoffee && (!gotWater || !gotJug || !gotMug))
		{
			g.setColor(Color.gray);
		}
		else if(!gotCoffee)
		{
			g.setColor(Color.red);
		}
		else
		{
			g.setColor(brown);
		}
		g.fillOval(200, 800, 50, 50);
		if(!gotNewspaper)
		{
			g.setColor(Color.red);
		}
		else
		{
			g.setColor(brown);
		}
		g.fillOval(250, 800, 50, 50);
		if(!gotNewspaper || !gotCoffee)
		{
			g.setColor(Color.gray);
		}
		else
		{
			g.setColor(Color.red);
		}
		g.fillOval(300, 800, 50, 50);

		g.drawImage(fusePicture, 0, 800, null);
		g.drawImage(mugPicture, 50, 800, null);
		g.drawImage(jugPicture, 100, 800, null);
		g.drawImage(waterPicture, 150, 800, null);
		g.drawImage(coffeeMachinePicture, 200, 800, null);
		g.drawImage(newspaperPicture, 250, 800, null);
		g.drawImage(ownDeskPicture, 300, 800, null);

		
		
		if(gameState == 0)
		{
			g.drawImage(mainMenuPicture, 100, 100, null);
		}
		else if(gameState == 3)
		{
			g.drawImage(lostScreenPicture, 100, 100, null);
		}
		else if(gameState == 2)
		{
			g.drawImage(wonScreenPicture, 100, 100, null);
		}
		
		
		g2.drawImage(newImage.getScaledInstance(xSize,ySize,BufferedImage.SCALE_SMOOTH), 0, 0, null);
		
		repaint();
		try {
			Thread.sleep(100);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

