package model.state;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.ArrayList;

import model.GameStateManager;
import model.InfoPanel;
import model.NetworkConnection;
import model.objects.Ball;
import model.objects.Player;
import model.objects.ShootingLine;
import resources.image.Images;
import resources.image.Images.ImageType;

public class PlayState extends State {

	private Player player1;
	private Player player2;
	private ShootingLine line1;
	private ShootingLine line2;
	private ArrayList<Ball> balls;
	private InfoPanel infopanel;
	private NetworkConnection nwc;
	private int timeleftpercent, direction, shoot;
	private String overlayText;
	private boolean matchStarted;

	public String chatMessage = "";
	public boolean typing = false;

	// The state in which the game runs
	public PlayState(GameStateManager gsm) {
		super("play", gsm);
		player1 = null;
		player2 = null;
	}

	/* NETWORK CONTROL */
	// This is called when a match has been made by the server
	public void newMatch(String p1, String p2) {
		player1 = new Player(Images.getImage(ImageType.PLAYER1), 40, 550, p1);
		player2 = new Player(Images.getImage(ImageType.PLAYER2), 90, 550, p2);
		infopanel = new InfoPanel(this);
		balls = new ArrayList<Ball>();
		typing = false;
		chatMessage = "";
		infopanel.clearChat();
		matchStarted = true;
	}

	/* INIT AND EXIT */

	// This is called when this state loads
	@Override
	public void init() {
		matchStarted = false;
		nwc = new NetworkConnection(this);
		try {
			nwc.connect(MenuState.name);
		} catch (IOException e) {
		}
	}

	// Close the match and connection
	@Override
	public void exit() {
		try {
			matchStarted = false;
			nwc.close();
		} catch (IOException e) {
		}
	}

	/* UPDATE AND PAINTING */
	public void updatePlayerInfo(int x, int y, int health, int score, Player player) {
		player.setX(x);
		player.setY(y);
		player.setHealth(health);
		player.setScore(score);
	}

	public void updateLines(int l1x, int l1y, int l1h, int l2x, int l2y, int l2h) {
		if (line1 == null)
			line1 = new ShootingLine(l1x, l1y);
		line1.setLength(l1h);
		line1.setStartx(l1x);
		line1.setStarty(l1y);
		if (line2 == null)
			line2 = new ShootingLine(l2x, l2y);
		line2.setLength(l2h);
		line2.setStartx(l2x);
		line2.setStarty(l2y);
	}

	@Override
	public void update() {
		if (player1 != null && player2 != null) {
			if (player1.getHealth() == 0 && player2.getHealth() == 0) {
				setOverlayText("Game over");
			}
			player1.update();
			player2.update();
		}
	}

	@Override
	public void paint(Graphics2D g2d) {
		g2d.drawImage(Images.getImage(ImageType.BACKGROUND), null, 0, 0);
		g2d.setColor(Color.RED);
		g2d.drawString(overlayText, 100, 300);
		g2d.setColor(Color.black);
		if (!matchStarted)
			return;
		if (line1 != null) {
			line1.paint(g2d);
		}
		if (line2 != null) {
			line2.paint(g2d);
		}
		for (Ball b : balls) {
			b.paint(g2d);
		}
		player1.paint(g2d);
		player2.paint(g2d);
		infopanel.paint(g2d);
	}

	/* GETTERS AND SETTERS */

	public Player getPlayer1() {
		return player1;
	}

	public Player getPlayer2() {
		return player2;
	}

	public int getTimeleftpercent() {
		return timeleftpercent;
	}

	public Ball getBall(int i) {
		try {
			return balls.get(i);
		} catch (IndexOutOfBoundsException e) {
			balls.add(i, new Ball());
			return balls.get(i);
		}
	}

	public ArrayList<Ball> getBalls() {
		return balls;
	}

	public void setTimeleftpercent(int timeleftpercent) {
		this.timeleftpercent = timeleftpercent;
	}

	public void setOverlayText(String text) {
		this.overlayText = text;
	}

	public void stopMatch() {
		try {
			nwc.close();
		} catch (IOException e) {
		}
		matchStarted = false;
	}

	/* EVENTS */
	@Override
	public void keyPressed(KeyEvent e) {
		if (!typing) {
			switch (e.getKeyCode()) {
			case KeyEvent.VK_RIGHT:
				direction = 1;
				break;
			case KeyEvent.VK_LEFT:
				direction = -1;
				break;
			case KeyEvent.VK_SPACE:
				shoot = 1;
				break;
			}
		} else {
			switch (e.getKeyCode()) {
			case KeyEvent.VK_ENTER:
				if (typing) {
					typing = false;
					if (chatMessage.length() > 0)
						nwc.sendChatMessage(chatMessage);
					chatMessage = "";
				}
			}
		}
		nwc.sendInput(direction, shoot);
	}

	@Override
	public void keyReleased(KeyEvent e) {
		if (!typing) {
			switch (e.getKeyCode()) {
			case KeyEvent.VK_RIGHT:
				direction = 0;
			case KeyEvent.VK_LEFT:
				direction = 0;
				break;
			case KeyEvent.VK_SPACE:
				shoot = 0;
				break;
			case KeyEvent.VK_ESCAPE:
				gsm.setState("menu");
				break;
			case KeyEvent.VK_C:
				typing = true;
				break;
			}
		} else {
			if (e.getKeyCode() != KeyEvent.VK_BACK_SPACE) {
				chatMessage += e.getKeyChar();
			} else if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE && chatMessage.length() > 0) {
				chatMessage = chatMessage.substring(0, chatMessage.length() - 1);
			}
		}
		nwc.sendInput(direction, shoot);
	}

	@Override
	public void keyTyped(KeyEvent e) {
	};

	// Add a chatmessage to this match
	public void addChatMessage(String msg) {
		infopanel.addChatMessage(msg);
	}
}
