/**
 * 
 */
package studio.junk.jam.coloritum;

import java.util.LinkedList;

import com.badlogic.ashley.core.Engine;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.EntitySystem;
import com.badlogic.ashley.core.Family;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.Disposable;

import box2dLight.Light;
import box2dLight.RayHandler;
import studio.junk.jam.coloritum.entities.components.Collision;
import studio.junk.jam.coloritum.entities.components.Lights;
import studio.junk.jam.coloritum.entities.systems.AnimationRender;
import studio.junk.jam.coloritum.entities.systems.LightBulbAligner;
import studio.junk.jam.coloritum.entities.systems.LightBulbController;
import studio.junk.jam.coloritum.entities.systems.LightWobbleController;
import studio.junk.jam.coloritum.entities.systems.SourceController;
import studio.junk.jam.coloritum.entities.systems.SpriteRender;
import studio.junk.jam.coloritum.entities.systems.UserInputHandler;
import studio.junk.jam.coloritum.screen.InGame;

/**
 * @author held03
 */
public class GameState implements Disposable {

	static LevelManager levelManager = new LevelManager();

	static {
		levelManager.parseScripts(Gdx.files.internal("scripts/levels/Init"));
	}

	public static GameState state;

	private static final int	RAYS_NUM	= 300;
	public Engine				engine;
	public World				world;

	public static final int	WORLD_WIDTH_PX	= 3840;
	public static final int	WORLD_HEIGHT_PX	= 2160;

	public static final int TILE_SIZE = 120;

	public static final int	WORLD_WIDTH_M	= WORLD_WIDTH_PX / TILE_SIZE;
	public static final int	WORLD_HEIGHT_M	= WORLD_HEIGHT_PX / TILE_SIZE;

	public static final Vector2 GRAVITY = new Vector2(0, 0);

	public static final float PULSE_INTERVAL = 2;

	public static final int MAX_EMISSION_PERIOD = 2;

	public static final float LIGHT_BULB_VEL = 1;

	public static final float	PX_TO_M	= 1f / TILE_SIZE;
	public static final float	M_TO_PX	= TILE_SIZE;

	public Texture backgroundImage;

	/**
	 * Entity type manager.
	 */
	public EntityTypeManager types;

	/**
	 * Maps asset names to Textures and animations.
	 */
	public AssetManager assets;

	/**
	 * Family defining entities which are used in Box2D context.
	 */
	@SuppressWarnings("unchecked")
	public static Family box2dEntities = Family.all(Collision.class).get();

	/**
	 * 
	 */
	public GameState() {
		// TODO Auto-generated constructor stub
	}

	LinkedList<Body> testBodys = new LinkedList<Body>();

	public void initAssets() {
		backgroundImage = new Texture("background/background.png");
		world = new World(GRAVITY, true);

		InGame.rayLightsHandler = new RayHandler(world);
	}

	public void init() {
		state = this;

		engine = new Engine();

		types = new EntityTypeManager();
		assets = new AssetManager();

		InGame.rayLightsHandler.setAmbientLight(0.2f, 0.2f, 0.2f, 0.7f);

		engine.addSystem(new AnimationRender());
		engine.addSystem(new SpriteRender());
		engine.addSystem(new LightBulbController());
		engine.addSystem(new SourceController());
		engine.addSystem(new LightBulbAligner());
		engine.addSystem(new LightWobbleController());

		Gdx.app.postRunnable(new Runnable() {
			@Override
			public void run() {
				engine.addSystem(new UserInputHandler());
			}
		});

		world.setContactListener(LightBulbController.contactListener);

		setLevel("base");
	}

	public void setLevel(String name) {
		levelManager.get(name).addEnvironment();
	}

	public void addEntity(Entity e) {

		engine.addEntity(e);
	}

	public void rmEntity(final Entity e) {
		Gdx.app.postRunnable(new Runnable() {

			@Override
			public void run() {
				if (!engine.getEntities().contains(e, true)) {
					System.err.println("Double remove Entity " + e);
					return;
				}

				if (Lights.mapper.has(e)) {
					Lights lights = Lights.mapper.get(e);
					//System.out.println("Dispose Light: " + e + " -> " + lights);
					for (Light l : lights.lights) {
						if (l != null) {
							//System.err.println("Entity " + e + " " + Name.mapper.get(e).name);
							l.remove();
						}
					}
				}

				if (box2dEntities.matches(e)) {

					Body body = Collision.mapper.get(e).body;
					body.setUserData(null);
					world.destroyBody(body);
					body = null;
				}

				engine.removeEntity(e);
			}
		});
	}


	public void update(float delta) {
		engine.update(delta);

		world.step(Gdx.graphics.getDeltaTime(), 6, 2);
	}

	@Override
	public void dispose() {
		for (EntitySystem es : engine.getSystems()) {
			if (es instanceof Disposable) {
				((Disposable) es).dispose();
			}
		}

		state = null;
	}

}
