package pl.shockah.ts.states;

import pl.shockah.glib.geom.Rectangle;
import pl.shockah.glib.geom.vector.Vector2d;
import pl.shockah.glib.geom.vector.Vector2i;
import pl.shockah.glib.gl.BlendMode;
import pl.shockah.glib.gl.GL;
import pl.shockah.glib.gl.Graphics;
import pl.shockah.glib.gl.Surface;
import pl.shockah.glib.gl.color.Color;
import pl.shockah.glib.gl.color.Colorb;
import pl.shockah.glib.logic.standard.Entities;
import pl.shockah.glib.logic.standard.EntityRenderable;
import pl.shockah.glib.state.State;
import pl.shockah.glib.state.View;
import pl.shockah.ts.Assets;
import pl.shockah.ts.entities.EntityBoxFading;
import pl.shockah.ts.entities.EntityBoxFalling;
import pl.shockah.ts.entities.EntityBoxPushable;
import pl.shockah.ts.entities.EntityDiamond;
import pl.shockah.ts.entities.EntityPlayer;
import pl.shockah.ts.entities.EntitySpikes;
import pl.shockah.ts.entities.EntityWall;
import pl.shockah.ts.entities.EntityWallHint;
import pl.shockah.ts.entities.effects.EffectOverlayTime;
import pl.shockah.ts.entities.hud.HudBlackBorders;
import pl.shockah.ts.entities.hud.HudHintDisplay;
import pl.shockah.ts.entities.waterblur.EffectWater;
import pl.shockah.ts.gameplay.Game;
import pl.shockah.ts.gameplay.TestLevel;

public class StateGame extends State {
	private static Surface surface = null;
	
	private final TestLevel l;
	
	public StateGame() {
		this(TestLevel.level1);
	}
	public StateGame(TestLevel l) {
		this.l = l;
		views.add(new View(new Vector2i(960,720)));
	}
	
	protected void onCreate() {
		Vector2i size = State.get().getDisplaySize();
		if (surface == null || !surface.image().getSize().equals(size)) {
			if (surface != null) surface.dispose();
			surface = Surface.create(size);
		}
		
		TestLevel level = l;
		Game.me = new Game(level.tileSize,level.theme);
		
		int idHint = 0;
		for (int y = 0; y < Game.me.tileSize.y; y++) for (int x = 0; x < Game.me.tileSize.x; x++) {
			char c = level.level.charAt(x+y*Game.me.tileSize.x);
			char c2 = level.water == null ? 0 : level.water.charAt(x+y*Game.me.tileSize.x);
			
			switch (c) {
				case '@': {
					new EntityPlayer().create(new Vector2d(x*24,y*24));
				} break;
				case '#': {
					new EntityWall().create(new Vector2d(x*24,y*24));
				} break;
				case '?': {
					new EntityWallHint(level.hints[idHint++]).create(new Vector2d(x*24,y*24));
				} break;
				case 'X': {
					new EntitySpikes().create(new Vector2d(x*24,y*24));
				} break;
				case '1': {
					new EntityDiamond(EntityDiamond.ERarity.Blue).create(new Vector2d(x*24,y*24));
				} break;
				case '2': {
					new EntityDiamond(EntityDiamond.ERarity.Red).create(new Vector2d(x*24,y*24));
				} break;
				case 'P': {
					new EntityBoxPushable().create(new Vector2d(x*24,y*24));
				} break;
				case 'G': {
					new EntityBoxFalling().create(new Vector2d(x*24,y*24));
				} break;
				case 'F': {
					new EntityBoxFading().create(new Vector2d(x*24,y*24));
				} break;
			}
			
			switch (c2) {
				case 'W': {
					Game.me.water[x][y] = true;
				} break;
			}
		}
		
		new EffectWater().create();
		new HudBlackBorders().create();
		
		new EffectOverlayTime().create();
		if (idHint != 0) new HudHintDisplay().create();
		
		new EntityRenderable(100000000){
			protected void onRender(Graphics g) {
				g.setRedirect(surface.graphics());
				g.clear(Color.Black);
				
				EntityPlayer player = Entities.getType(EntityPlayer.class).get(0);
				Vector2i size = State.get().getDisplaySize();
				Game.me.translateV.set(size.x/2d-player.pos.x-12,size.y/2d-player.pos.y-12);
				if (Game.me.tileSize.x*24 <= size.x) Game.me.translateV.x = -(Game.me.tileSize.x*24-size.x)/2;
				if (Game.me.tileSize.y*24 <= size.y) Game.me.translateV.y = -(Game.me.tileSize.y*24-size.y)/2;
				g.translate(Game.me.translateV);
				
				g.toggleAbsolute();
				GL.translated(Game.me.translateV.Negate());
				Color c1 = new Colorb(0,138,255), c2 = new Colorb(255,167,68);
				new Rectangle(State.get().getDisplaySize()).drawMulticolor(g,true,c1,c1,c2,c2);
				GL.translated(Game.me.translateV);
				g.toggleAbsolute();
			}
		}.create();
		new EntityRenderable(-1000000){
			protected void onRender(Graphics g) {
				g.clearRedirect();
				
				boolean useShader = Math.min(EffectOverlayTime.me.a1+EffectOverlayTime.me.a2,.5f)*2f > 0;
				if (useShader) {
					GL.bind(Assets.sdrTimeEffect);
					GL.boundShader().setUniform("ratio1",EffectOverlayTime.me.a2*2f);
					GL.boundShader().setUniform("ratio2",Math.min(EffectOverlayTime.me.a1+EffectOverlayTime.me.a2,.5f)*2f);
				}
				
				BlendMode.Off.apply();
				g.setColor(Color.White);
				g.draw(surface.image());
				if (useShader) GL.unbindShader();
				Graphics.getDefaultBlendMode().apply();
				
				//fps = 10000;
				//Display.setTitle("FPS: "+Debug.current.fps);
			}
		}.create();
	}
}