package client.renderer.tileentity;

import java.util.Iterator;
import java.util.Map;

import org.lwjgl.opengl.GL11;

import client.Client;
import client.renderer.Drawing;
import client.renderer.GlState;
import client.renderer.texture.DynamicTexture;
import common.block.Block;
import common.block.tech.BlockDisplay;
import common.collect.Maps;
import common.tileentity.TileEntityDisplay;
import common.util.BlockPos;
import common.util.Facing;
import common.world.State;

public class DisplayRenderer extends ElementRenderer<TileEntityDisplay> {
	private static class TimedTexture {
		public long time;
		public long updated;
		public String texture;
	}

	private static final Map<String, TimedTexture> DISPLAYS = Maps.<String, TimedTexture>newHashMap();

	private static String getTextureLocation(BlockPos pos) {
		return "display/" + pos.getX() + "," + pos.getY() + "," + pos.getZ();
	}

	private static String getTexture(TileEntityDisplay te) {
		String id = getTextureLocation(te.getPos());
		TimedTexture tex = DISPLAYS.get(id);

		if(tex == null) {
			if(DISPLAYS.size() >= 256) {
				long i = System.currentTimeMillis();
				Iterator<String> iterator = DISPLAYS.keySet().iterator();

				while(iterator.hasNext()) {
					String oid = iterator.next();
					TimedTexture ttex = DISPLAYS.get(oid);

					if(i - ttex.time > 60000L) {
						Client.CLIENT.getTextureManager().deleteTexture(ttex.texture);
						iterator.remove();
					}
				}

				if(DISPLAYS.size() >= 256) {
					return null;
				}
			}

			tex = new TimedTexture();
			tex.texture = id;
			tex.updated = te.lastUpdated;
			DynamicTexture dtex = new DynamicTexture(te.density, te.density);
			System.arraycopy(te.data, 0, dtex.getData(), 0, te.data.length);
			dtex.updateTexture();
			Client.CLIENT.getTextureManager().loadTexture(tex.texture, dtex);
			DISPLAYS.put(id, tex);
		}
		else if(te.lastUpdated != tex.updated) {
			tex.updated = te.lastUpdated;
			if(Client.CLIENT.getTextureManager().getTexture(tex.texture) instanceof DynamicTexture dtex) {
				if(dtex.getWidth() * dtex.getHeight() != te.data.length) {
					Client.CLIENT.getTextureManager().deleteTexture(tex.texture);
					Client.CLIENT.getTextureManager().loadTexture(tex.texture, dtex = new DynamicTexture(te.density, te.density));
				}
				System.arraycopy(te.data, 0, dtex.getData(), 0, te.data.length);
				dtex.updateTexture();
			}
		}

		tex.time = System.currentTimeMillis();
		return tex.texture;
	}

	public void renderElements(TileEntityDisplay te, double x, double y, double z, float partialTicks) {
		Block block = te.getBlock();

		State state = te.getState();
		Facing dir = state.getBlock() instanceof BlockDisplay ? state.getValue(BlockDisplay.FACING) : Facing.SOUTH;
		float rot = 0.0F;
		if(dir == Facing.NORTH)
			rot = 180.0F;
		else if(dir == Facing.WEST)
			rot = 90.0F;
		else if(dir == Facing.EAST)
			rot = -90.0F;

		GL11.glPushMatrix();
		GL11.glTranslatef((float)x + 0.5F, (float)y + 1.0f, (float)z + 0.5F);
		GL11.glRotatef(-rot, 0.0F, 1.0F, 0.0F);
		GL11.glTranslatef(-0.5F, 0.0f, -0.5f + 0.0625f + 0.005f);
		float density = 1.0f / (float)(te.density / 16);
		GL11.glScalef(0.0625f * density, -0.0625f * density, 0.0625f * density);

		GlState.disableLighting();
		Drawing.drawTexturedRect(Client.CLIENT, getTexture(te), te.density, te.density, 0, 0, 0, 0, te.density, te.density);
		GlState.enableLighting();

		GlState.color(1.0F, 1.0F, 1.0F, 1.0F);
		GL11.glPopMatrix();
	}
}
