package de.samdev.colorrunner.game.world.entities.gameentities;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.graphics.Texture;

import de.samdev.colorrunner.CRGame;
import de.samdev.colorrunner.game.renderer.CRAssets;
import de.samdev.colorrunner.game.world.CRGameWorld;
import de.samdev.colorrunner.game.world.SwipeDirection;
import de.samdev.colorrunner.game.world.entities.CRGameEntity;
import de.samdev.colorrunner.game.world.entities.MovingEntity;
import de.samdev.colorrunner.game.world.entities.gameentities.controller.AbstractPlayerController;
import de.samdev.colorrunner.game.world.entities.gameentities.controller.GravityPlayerController;
import de.samdev.colorrunner.game.world.entities.gameentities.controller.RunBottomPlayerController;
import de.samdev.colorrunner.game.world.entities.gameentities.controller.FlyPlayerController;
import de.samdev.colorrunner.game.world.entities.gameentities.controller.RunTopPlayerController;
import de.samdev.colorrunner.game.world.entities.gameentities.floor.FloorTileEntity;
import de.samdev.colorrunner.game.world.map.CRMapStorage;
import de.samdev.colorrunner.game.world.map.provider.StaticMapProvider;
import de.samdev.colorrunner.game.world.map.provider.TriggerType;
import de.samdev.colorrunner.screens.gameScreen.GameScreen;

public class PlayerEntity extends MovingEntity {
	public final static float PLAYER_WIDTH = 31.9f;
	public final static float PLAYER_HEIGHT = 31.9f;

	public final static float PLAYER_SPEED_FORCE = 166f;
	public final static float PLAYER_TERMINAL_SPEED = 320f;

	public final static float PLAYER_ROTATION_SPEED = -200f;

	private SwipeDirection phase = SwipeDirection.UP;

	private AbstractPlayerController controller;

	private Preferences ingameprefs = Gdx.app.getPreferences("ingamepreferences");

	public PlayerEntity(CRGameWorld _owner, float x, float y) {
		super(_owner, x, y, PLAYER_WIDTH, PLAYER_HEIGHT);

		controller = new RunBottomPlayerController(this);
	}

	@Override
	public void update(float delta) {
		if (velocity.x < PLAYER_TERMINAL_SPEED)
			velocity.x += PLAYER_SPEED_FORCE * delta;

		updateRotation(delta);

		TriggerType trigger = getTrigger();
		switch (trigger){
			case RUNTOP:
				if (controller.getControllerType() != ControllingType.RUNTOP) controller = new RunTopPlayerController(this);
				break;
			case RUNBOTTOM:
				if (controller.getControllerType() != ControllingType.RUNBOTTOM) controller = new RunBottomPlayerController(this);
				break;
			case FLY:
				if (controller.getControllerType() != ControllingType.FLY) controller = new FlyPlayerController(this);
				break;
			case GRAVITY:
				if (controller.getControllerType() != ControllingType.GRAVITY) controller = new GravityPlayerController(this);
				break;
			case END:
				//((Game)Gdx.app.getApplicationListener()).setScreen(new MainMenu());

				int currantlvl = ingameprefs.getInteger("currantlvl", 1);
				currantlvl++;


				int highestlevel = ingameprefs.getInteger("highestlevel", 1);
				if(currantlvl > highestlevel)
					highestlevel = currantlvl;

				ingameprefs.putInteger("highestlevel", highestlevel);
				ingameprefs.putInteger("currantlvl", currantlvl);
				ingameprefs.flush();

				int maximumlvl = 4;
				//TODO ::
				//if(currantlvl > maximumlvl)
				//	((Game)Gdx.app.getApplicationListener()).setScreen(new MainMenu());
				//else
				//	CRGame.Inst().setScreen(new GameScreen(new StaticMapProvider(CRMapStorage.map_map.get(currantlvl))));

				world.music.stop();
				break;
		}

		controller.update(delta);

		super.update(delta);
	}

	private void updateRotation(float delta) {
		boolean touch = isTouching_ANY();
		boolean aligned = (visualRotation % 90 == 0);

		if (!touch)
		{
			visualRotation = visualRotation + PLAYER_ROTATION_SPEED * delta;
			visualRotation = (visualRotation + 720f) % 360f;

			float p = (float) ((Math.max(Math.abs(Math.cos(Math.toRadians(visualRotation + 45))), Math.abs(Math.sin(Math.toRadians(visualRotation + 45)))) * Math.sqrt(PLAYER_WIDTH * PLAYER_WIDTH + PLAYER_HEIGHT * PLAYER_HEIGHT)));
			updateHitBox(p, p);
		}
		else if (touch && aligned)
		{
			// all ok - move along
		}
		else if (touch && !aligned)
		{
			visualRotation = (visualRotation + 720f) % 90f;

			if (visualRotation < 45) visualRotation = visualRotation + PLAYER_ROTATION_SPEED * delta;
			else                     visualRotation = visualRotation - PLAYER_ROTATION_SPEED * delta;

			if (visualRotation >= 90f || visualRotation <= 0f) visualRotation = 0f;

			visualRotation = (visualRotation + 720f) % 90f;

			float p = (float) ((Math.max(Math.abs(Math.cos(Math.toRadians(visualRotation + 45))), Math.abs(Math.sin(Math.toRadians(visualRotation + 45)))) * Math.sqrt(PLAYER_WIDTH * PLAYER_WIDTH + PLAYER_HEIGHT * PLAYER_HEIGHT)));
			updateHitBox(p, p);
		}
		else
		{
			Gdx.app.error("PlayerEntity", "updateRotation::WTF");
		}
	}

	public void jumpPressed() {
		controller.jumpPressed();
	}

	public void switchPhase(SwipeDirection sd) {
		if (phase == sd) return;
		phase = sd;
		
		for (CRGameEntity ent : world.entities) {
			if (ent == this) continue;
			
			if (ent.bounds.overlaps(bounds) && ent.canCollide(false, this) && ent instanceof FloorTileEntity)
				ent.remove();
				
		}
	}

	@Override
	public Texture getTexture() {
		switch (phase) {
		case UP:
			return CRAssets.TEX_PLAYER_UP;
		case RIGHT:
			return CRAssets.TEX_PLAYER_RIGHT;
		case DOWN:
			return CRAssets.TEX_PLAYER_DOWN;
		case LEFT:
			return CRAssets.TEX_PLAYER_LEFT;

		default:
			return null;
		}
	}

	@Override
	public boolean canCollide(boolean actualCollision, CRGameEntity collider) {
		return collider.canCollide(actualCollision, this);
	}

	public SwipeDirection getPhase() {
		return phase;
	}
}
