package com.eyeofmidas.cardtrick;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.utils.Scaling;
import com.eyeofmidas.cardtrick.InputScreen.DragDirection;

public class TrainingScreen implements Screen {

	private CardtrickGame game;
	private TextureAtlas cardAtlas;
	private Vector2 randomTile;
	private Vector2 startPosition;
	private Vector2 startTile;
	private Vector2 tileSize;
	private int runningScore;
	private boolean isSelected;
	private DragDirection randomDirection;
	private Image cardImage;
	private Image wrongArrow;
	private Image correctArrow;
	private Label scoreLabel;
	private DragDirection dragDirection;
	private ShapeRenderer shapeRenderer;
	private boolean isTouching;
	private boolean isActive;

	public TrainingScreen() {
		game = (CardtrickGame) Gdx.app.getApplicationListener();
		shapeRenderer = game.getShapeRenderer();

	}

	@Override
	public void render(float delta) {
		game.getStage().act(delta);

		Gdx.gl.glClearColor(0, 0, 0, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

		game.getStage().draw();

		if (isSelected) {
			wrongArrow.setVisible(true);

			if (isCorrectTile() && dragDirection == randomDirection) {
				runningScore++;
				correctArrow.setVisible(true);
				resetAndReroll();
			} else {
				isSelected = false;
				runningScore = 0;
				scoreLabel.setText("Score: " + runningScore);
			}
		}

		shapeRenderer.setProjectionMatrix(game.getStage().getCamera().combined);
		ShapeType shape = ShapeType.Line;
		Color selectColor = Color.RED;
		if (isActive) {
			if (isCorrectTile()) {
				selectColor = Color.GREEN;
			}
			if (isTouching) {
				shape = ShapeType.Filled;
			}
			shapeRenderer.begin(shape);
			shapeRenderer.setColor(selectColor);
			shapeRenderer.rect(startTile.x * tileSize.x, (3 - startTile.y) * tileSize.y, tileSize.x, tileSize.y);
			shapeRenderer.end();
		}
	}

	private boolean isCorrectTile() {
		return startTile.equals(randomTile) || (startTile.y == randomTile.y && randomTile.y == 3);
	}

	@Override
	public void resize(int width, int height) {
		game.getStage().getViewport().update(width, height, true);
		tileSize.x = (game.getStage().getWidth() * 0.25f);
		tileSize.y = (game.getStage().getHeight() * 0.25f);

	}

	@Override
	public void show() {
		game.getStage().clear();
		cardAtlas = game.getAssetManager().get("data/cards.atlas", TextureAtlas.class);

		randomTile = new Vector2();
		startPosition = new Vector2();
		startTile = new Vector2();
		tileSize = new Vector2();
		tileSize.x = (game.getStage().getWidth() * 0.25f);
		tileSize.y = (game.getStage().getHeight() * 0.25f);
		runningScore = 0;

		isSelected = false;

		resetAndReroll();
	}

	private void reroll() {
		randomTile.x = (int) Math.floor(Math.random() * 4);
		randomTile.y = (int) Math.floor(Math.random() * 4);
		randomDirection = randomEnum(DragDirection.class);
	}

	private void resetAndReroll() {
		isActive = false;
		game.getStage().clear();

		game.getStage().addListener(new InputListener() {

			@Override
			public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
				isSelected = false;
				isActive = true;
				isTouching = true;
				startPosition.x = x;
				startPosition.y = y;

				startTile.x = MathUtils.floor(startPosition.x / tileSize.x);
				startTile.y = 3 - MathUtils.floor(startPosition.y / tileSize.y);
				return true;
			}

			@Override
			public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
				isSelected = true;
				isTouching = false;
				Vector2 delta = new Vector2();
				delta.x = startPosition.x - x;
				delta.y = startPosition.y - y;
				if (Math.abs(delta.x) > Math.abs(delta.y)) {
					if (delta.x > 0) {
						dragDirection = DragDirection.LEFT;
					} else {
						dragDirection = DragDirection.RIGHT;
					}
				} else {
					if (delta.y < 0) {
						dragDirection = DragDirection.UP;
					} else {
						dragDirection = DragDirection.DOWN;
					}
				}
				Gdx.app.log("EyeOfMidas", startTile.toString() + dragDirection.toString());
			}

			@Override
			public void touchDragged(InputEvent event, float x, float y, int pointer) {
				// startTile.x = MathUtils.floor(x / tileSize.x);
				// startTile.y = 3 - MathUtils.floor(y / tileSize.y);
			}

			@Override
			public boolean keyDown(InputEvent event, int keyCode) {
				switch (keyCode) {
				case Input.Keys.BACK:
				case Input.Keys.ESCAPE:
					game.goMainMenu();
					break;
				}
				return false;
			}
		});

		Gdx.input.setInputProcessor(game.getStage());
		Gdx.input.setCatchBackKey(true);

		isSelected = false;
		isTouching = false;

		reroll();

		String cardName = (String) CardTranslator.translate(randomTile, randomDirection);
		String cleanedCardName = cardName.toLowerCase().replaceAll(" ", "-");
		Sprite cardSprite = cardAtlas.createSprite(cleanedCardName);
		cardSprite.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
		cardImage = new Image(cardSprite);
		cardImage.setSize(game.getStage().getWidth() * 0.75f, game.getStage().getHeight() * 0.75f);
		cardImage.setScaling(Scaling.fit);
		cardImage.setAlign(Align.center);
		cardImage.setPosition((game.getStage().getWidth() - cardImage.getWidth()) / 2, (game.getStage().getHeight() - cardImage.getHeight()) / 2);
		game.getStage().addActor(cardImage);

		String arrowFacing = "";
		switch (randomDirection) {
		case DOWN:
			arrowFacing = "down";
			break;
		case LEFT:
			arrowFacing = "left";
			break;
		case RIGHT:
			arrowFacing = "right";
			break;
		case UP:
			arrowFacing = "up";
			break;
		default:
			arrowFacing = "up";
			break;

		}
		wrongArrow = new Image(game.getSkin().newDrawable(arrowFacing, Color.RED));
		wrongArrow.setSize(tileSize.x, tileSize.y);
		wrongArrow.setScaling(Scaling.fit);
		wrongArrow.setPosition(randomTile.x * tileSize.x, (3 - randomTile.y) * tileSize.y);
		game.getStage().addActor(wrongArrow);
		correctArrow = new Image(game.getSkin().newDrawable(arrowFacing, Color.GREEN));
		correctArrow.setSize(tileSize.x, tileSize.y);
		correctArrow.setScaling(Scaling.fit);
		correctArrow.setPosition(randomTile.x * tileSize.x, (3 - randomTile.y) * tileSize.y);
		game.getStage().addActor(correctArrow);
		wrongArrow.setVisible(false);
		correctArrow.setVisible(false);

		scoreLabel = new Label("Score: " + runningScore, game.getSkin());
		scoreLabel.setPosition(0, game.getStage().getHeight() - scoreLabel.getHeight());
		game.getStage().addActor(scoreLabel);
	}

	public static <T extends Enum<?>> T randomEnum(Class<T> clazz) {
		int x = (int) Math.floor(Math.random() * clazz.getEnumConstants().length);
		return clazz.getEnumConstants()[x];
	}

	@Override
	public void hide() {
		// TODO Auto-generated method stub

	}

	@Override
	public void pause() {
		// TODO Auto-generated method stub

	}

	@Override
	public void resume() {
		// TODO Auto-generated method stub

	}

	@Override
	public void dispose() {
		// TODO Auto-generated method stub

	}

}
