package zero1hd.polyjet.screens;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;

import zero1hd.polyjet.Polyjet;
import zero1hd.polyjet.audio.AudioData;
import zero1hd.polyjet.audio.map.GamePlayMap;
import zero1hd.polyjet.ui.stages.GamePlayArea;
import zero1hd.polyjet.ui.windows.FPSWindow;

public class GameScreen extends ScreenAdapter implements InputProcessor {
	private GamePlayArea gameArea;
	public InputMultiplexer inputs;

	public boolean paused = false;
	private boolean debug = false;

	public Polyjet core;
	public Stage overlay;
	private Label scoreLabel;
	Window pauseMenu;
	FPSWindow FPSDisplay;

	private AudioData music;
	
	public GameScreen(Polyjet polyJet, GamePlayMap gpm) {
		core = polyJet;
		
		// Overlay stuff
		overlay = new Stage();
		scoreLabel = new Label("Score: 0", core.getDefaultSkin(), "default-font", Color.WHITE);
		scoreLabel.setPosition(25, Gdx.graphics.getHeight() - scoreLabel.getHeight() - 25);

		ImageButton pause = new ImageButton(core.getDefaultSkin().getDrawable("pause"),
				core.getDefaultSkin().getDrawable("pause-down"));
		pause.setPosition(Gdx.graphics.getWidth() - pause.getWidth() - 25,
				Gdx.graphics.getHeight() - pause.getHeight() - 25);
		pause.addListener(new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				pause();
			}
		});

		WidgetGroup healthBar = new WidgetGroup();
		final Image healthBarTank = new Image(core.getDefaultSkin().getPatch("bar-empty"));
		healthBarTank.setHeight(100);
		healthBar.setSize(healthBarTank.getWidth(), healthBarTank.getHeight());
		healthBar.setPosition(Gdx.graphics.getWidth() - healthBar.getWidth() - 16,
				pause.getY() - healthBar.getHeight() - 32);

		Image healthBarFiller = new Image(core.getDefaultSkin().getPatch("bar-fill")) {
			@Override
			public void act(float delta) {
				setHeight(
						((float) gameArea.getPolyjet().health / (float) gameArea.getMaxHealth()) * (healthBarTank.getHeight()));
				super.act(delta);
			}
		};
		healthBar.addActor(healthBarFiller);
		healthBar.addActor(healthBarTank);
		overlay.addActor(healthBar);

		FPSDisplay = new FPSWindow("FPS", core.getDefaultSkin());
		overlay.addActor(pause);
		overlay.addActor(scoreLabel);

		// Pause menu
		pauseMenu = new Window("Paused", core.getDefaultSkin());
		pauseMenu.add(new TextButton("resume", core.getDefaultSkin()) {
			{
				addListener(new ChangeListener() {

					@Override
					public void changed(ChangeEvent event, Actor actor) {
						reBegin();
					}
				});
			}
		}).space(20f);
		pauseMenu.setModal(true);
		pauseMenu.setPosition((Gdx.graphics.getWidth() - pauseMenu.getWidth()) / 2,
				(Gdx.graphics.getHeight() - pauseMenu.getHeight()) / 2);

		// Continue to add things to input multiplexer
		gameArea = new GamePlayArea(polyJet.getAssetManager(), core.getPrefs());
		gameArea.setAudioMap(gpm);
		
		inputs = new InputMultiplexer();
		inputs.addProcessor(this);
		inputs.addProcessor(overlay);
		inputs.addProcessor(gameArea);

		if (!paused) {
			music.getPlaybackMusic().play();
		}
	}
	
	@Override
	public void show() {
		Gdx.input.setInputProcessor(inputs);
		gameArea.loadShaders(core.getPrefs());
		super.show();
	}

	@Override
	public void render(float delta) {
		Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
		Gdx.gl.glLineWidth(1f);
		gameArea.getViewport().apply();
		
		gameArea.draw();
		
		overlay.getViewport().apply();
		overlay.draw();
		if (!paused) {
			music.readIndexUpdate();
			scoreLabel.setText("Score: " + gameArea.getScore());
			gameArea.act(delta);

			if (gameArea.getPolyjet().isDead()) {
				end(false);
			}

			overlay.act(delta);
		}

		if (!music.getPlaybackMusic().isPlaying()) {
			end(true);
		}
		
		super.render(delta);
	}

	private void end(boolean trueEnd) {
		if (trueEnd) {
			// TODO they didn't die
		} else {
			// TODO They done goofed and ended up dying.
		}
	}

	@Override
	public void dispose() {
		overlay.dispose();
		gameArea.dispose();
		super.dispose();
	}

	@Override
	public void resize(int width, int height) {
		gameArea.getViewport().update(width, height, true);
		overlay.getViewport().update(width, height, true);

		super.resize(width, height);
	}

	@Override
	public void pause() {
		paused = true;
		overlay.addActor(pauseMenu);
		music.getPlaybackMusic().pause();
		super.pause();
	}

	@Override
	public void resume() {
		super.resume();
	}

	public void reBegin() {
		paused = false;
		pauseMenu.remove();
		music.getPlaybackMusic().play();
	}

	@Override
	public boolean keyUp(int keycode) {
		switch (keycode) {
		case Keys.F3:
			if (debug) {
				debug = false;
				for (int i = 0; i < gameArea.getActors().size; i++) {
					gameArea.setDebugAll(debug);
				}
				FPSDisplay.remove();
			} else {
				debug = true;
				for (int i = 0; i < gameArea.getActors().size; i++) {
					gameArea.setDebugAll(debug);
				}
				overlay.addActor(FPSDisplay);
			}

			break;

		case Keys.ESCAPE:
			if (paused) {
				reBegin();
			} else {
				pause();
			}
			break;
		}
		return false;
	}

	@Override
	public boolean keyTyped(char character) {
		return false;
	}

	@Override
	public boolean mouseMoved(int screenX, int screenY) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean scrolled(int amount) {
		return false;
	}

	@Override
	public boolean keyDown(int keycode) {
		return false;
	}

	@Override
	public boolean touchDown(int screenX, int screenY, int pointer, int button) {
		return false;
	}

	@Override
	public boolean touchUp(int screenX, int screenY, int pointer, int button) {
		return false;
	}

	@Override
	public boolean touchDragged(int screenX, int screenY, int pointer) {
		return false;
	}
}