package studio.junk.jam.coloritum.ui.systems;

import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.systems.IteratingSystem;
import com.badlogic.ashley.utils.ImmutableArray;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Buttons;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.BoundingBox;

import studio.junk.jam.coloritum.screen.InGame;
import studio.junk.jam.coloritum.ui.animation.Animation;
import studio.junk.jam.coloritum.ui.animation.Animator;
import studio.junk.jam.coloritum.ui.animation.AnimatorCallback;
import studio.junk.jam.coloritum.ui.animation.InterpolationFunction;
import studio.junk.jam.coloritum.ui.components.Menu;
import studio.junk.jam.coloritum.ui.components.MenuEntries;

public class MenuInteraction extends IteratingSystem {
	@SuppressWarnings("unchecked")
	public static final Family family = Family.all(MenuEntries.class).get();


	public MenuInteraction(int priority) {
		super(family, priority);
		// TODO Auto-generated constructor stub
	}

	public MenuInteraction() {
		super(family);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void processEntity(Entity entity, float deltaTime) {
		// TODO Auto-generated method stub

	}

	private static class IntersectionData {
		public String				menuId;
		public MenuEntries.Entry	menuEntry;

		public IntersectionData(String menuId, MenuEntries.Entry menuEntry) {
			this.menuId = menuId;
			this.menuEntry = menuEntry;
		}
	}

	@SuppressWarnings("unchecked")
	private static IntersectionData getIntersection(float uiX, float uiY) {
		ImmutableArray<Entity> entities = InGame.currentGame.engineUI
				.getEntitiesFor(Family.all(Menu.class, MenuEntries.class).get());

		Entity[] ens = entities.toArray(Entity.class);


		for (Entity e : ens) {
			Menu menu = Menu.mapper.get(e);
			MenuEntries entries = MenuEntries.mapper.get(e);

			if (!menu.visible)
				continue;
			BoundingBox menuBb = MenuRender.getMenuBoundingBox(menu.id);
			if (menuBb.contains(new Vector3(uiX, uiY, 0))) {
				int indexX = (int) ((uiX - menuBb.min.x) / MenuRender.MENU_ITEM_WIDTH);
				int indexY = (int) ((uiY - menuBb.min.y) / MenuRender.MENU_ITEM_HEIGHT);
				return new IntersectionData(menu.id, entries.entries.get(menu.horizontal ? indexX : indexY));
			}
		}

		return null;
	}

	private static boolean mainMenuShown = false;

	public static void onTouch(float uiX, float uiY, int button, Entity entityUnderCursor) {
		if (button == Buttons.LEFT && entityUnderCursor == null) {
			IntersectionData intersect = getIntersection(uiX, uiY);
			if (intersect == null) {
				hideAllMenus();
				showMenu("mainMenu", new Vector2(uiX, uiY), 800);
			} else {
				String action = intersect.menuEntry.action;
				if (action == "showMenu") {
					String newMenuId = (String) intersect.menuEntry.actionData;
					showMenu(newMenuId, new Vector2(uiX, uiY), 800);
				} else if (action == "addLightSource") {
					// TODO add light source
				} else if (action == "addMirror") {
					// TODO add mirror
				}
			}
		} else if (button == Buttons.RIGHT) {
			hideAllMenus();
		}
	}

	public static void showMenu(String menuId, Vector2 position, long duration) {
		showMenu(Menu.getMenu(menuId), position, duration, new InterpolationFunction.Linear());
	}

	public static void showMenu(Entity entity, Vector2 position, long duration, InterpolationFunction func) {

		final Menu menu = Menu.mapper.get(entity);

		if (menu.visible == true) {
			return;
		}

		menu.visible = true;
		menu.position.set(position);

		Animator.animate(new Animation(0, 1, duration, new AnimatorCallback() {

			@Override
			public void callback(double value) {
				menu.opacity = value;
			}
		}, func, Gdx.graphics.getFramesPerSecond(), false));
	}

	public static void showMenu(Entity entity, Vector2 position) {
		showMenu(entity, position, 800, new InterpolationFunction.Linear());
	}

	@SuppressWarnings("unchecked")
	public static void hideAllMenus() {
		for (Entity e : InGame.currentGame.engineUI.getEntitiesFor(Family.all(Menu.class, MenuEntries.class).get())) {
			hideMenu(e);
		}
	}

	public static void hideMenu(String menuId) {
		hideMenu(Menu.getMenu(menuId));
	}

	public static void hideMenu(Entity entity) {
		final Menu menu = Menu.mapper.get(entity);
		if (!menu.visible) {
			return;
		}
		menu.visible = false;

		Animator.animate(new Animation(1, 0, 300, new AnimatorCallback() {

			@Override
			public void callback(double value) {
				menu.opacity = value;
			}
		}, new InterpolationFunction.Linear(), Gdx.graphics.getFramesPerSecond(), false));
	}

}
