/*
Ace of Spades remake
Copyright (C) 2013 ByteBit

This program is free software; you can redistribute it and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program;
if not, see <http://www.gnu.org/licenses/>.
*/


package bin;
import java.io.InputStream;
import java.util.Random;

import javax.media.opengl.GL2;

public class Entity {
    public int[][][] objectdata = new int[64][64][64];
    public float[][][] objectshading = new float[64][64][64]; //stores the shading
    public World world;
    public float posX = 0.0F;
    public float posY = 0.0F;
    public float posZ = 0.0F;
    public float rot_x = 0.0F;
    public float rot_y = 0.0F;
    public float rot_z = 0.0F;
    private Random rand = new Random();
    public int x_size = 0;
    public int y_size = 0;
    public int z_size = 0;
    public boolean scale = false;
    public float color_red = 0.0F;
    public float color_green = 1.0F;
    public float color_blue = 0.0F;
    public boolean init = true;
    private int list = 0;
    
    public float gray = 1.0F;
    
    public Entity(World w) {
    	this.world = w;
    }
    
    public void setColor(float red, float green, float blue) {
    	this.color_red = red;
    	this.color_green = green;
    	this.color_blue = blue;
    }
    
    public void setPosition(float x, float y, float z) {
    	this.posX = x;
    	this.posY = y;
    	this.posZ = z;
    }
    
    public void setRotation(float x, float y, float z) {
    	rot_x = x;
    	rot_y = y;
    	rot_z = z;
    }
    
    public void loadVoxelData(String src) {
			 try {
			     InputStream in = this.getClass().getResourceAsStream(src);
			     this.x_size = in.read();
			     this.y_size = in.read();
			     this.z_size = in.read();
				 for(int z=0; z<this.z_size; z++) {
						for(int x=0;x<this.x_size;x++) {
							for(int y=0; y<this.y_size; y++) {
							int i = in.read();
							switch(i) {
							case 49:
								this.objectdata[x][y][z] = 1;
								break;
							case 50:
								this.objectdata[x][y][z] = 2;
								break;
							case 51:
								this.objectdata[x][y][z] = 3;
								break;
							case 52:
								this.objectdata[x][y][z] = 4;
								break;
							case 53:
								this.objectdata[x][y][z] = 5;
								break;
							case 54:
								this.objectdata[x][y][z] = 6;
								break;
							case 55:
								this.objectdata[x][y][z] = 7;
								break;
							case 56:
								this.objectdata[x][y][z] = 8;
								break;
							case 57:
								this.objectdata[x][y][z] = 9;
								break;
							case 58:
								this.objectdata[x][y][z] = 10;
								break;
							default:
								this.objectdata[x][y][z] = 0;
								break;
							}
						    this.objectshading[x][y][z] = rand.nextFloat()*0.125F+0.75F+0.125F;
							}
						}
					}
				 in.close();
			     } catch(Exception e) { System.err.println("Error while loading a kv6 file from "+src+" Exception: "+e); }
    }
    
    public int getBlock(int x, int y, int z) {
    	if(x>-1 && x<this.x_size && y>-1 && y<this.y_size && z>-1 && z<this.z_size) {
   		 return objectdata[x][y][z];
   	 }
   	 return 0;
    }
	
	public void render(GL2 gl2) {
		if(init) {
			this.list = gl2.glGenLists(1);
			gl2.glNewList(this.list, GL2.GL_COMPILE);
			for(int z=0; z!=this.z_size; z++) { for(int x=0; x!=this.x_size; x++) { for(int y=0; y!=this.y_size; y++) {
				if(getBlock(x,y,z)!=0) {
		            switch(getBlock(x,y,z)) {
		             case 1:
		                 gl2.glColor3f(0.8470588235294118F*this.objectshading[x][y][z]*gray,0.6431372549019608F*this.objectshading[x][y][z]*gray,0.4235294117647059F*this.objectshading[x][y][z]*gray);
		                 break;
		             case 2:
		            	 gl2.glColor3f(this.color_red*this.objectshading[x][y][z]*gray,this.color_green*this.objectshading[x][y][z]*gray,this.color_blue*this.objectshading[x][y][z]*gray);
		            	 break;
		             case 3:
		            	 gl2.glColor3f(0.2196078431372549F*this.objectshading[x][y][z]*gray,0.1568627450980392F*this.objectshading[x][y][z]*gray,0.1098039215686275F*this.objectshading[x][y][z]*gray);
		            	 break;
		             case 4:
		            	 gl2.glColor3f(0.0F*this.objectshading[x][y][z]*gray,0.0F*this.objectshading[x][y][z]*gray,0.0F*this.objectshading[x][y][z]*gray);
		            	 break;
		             case 5:
		            	 gl2.glColor3f(0.3294117647058824F*this.objectshading[x][y][z]*gray,0.3294117647058824F*this.objectshading[x][y][z]*gray,0.3294117647058824F *this.objectshading[x][y][z]*gray);
		            	 break;
		             case 6:
		            	 gl2.glColor3f(0.4235294117647059F*this.objectshading[x][y][z]*gray,0.3294117647058824F*this.objectshading[x][y][z]*gray,0.2196078431372549F*this.objectshading[x][y][z]*gray);
		            	 break;
		             case 7:
		            	 gl2.glColor3f(0.0F*this.objectshading[x][y][z]*gray,0.6274509803921569F*this.objectshading[x][y][z]*gray,0.0F*this.objectshading[x][y][z]*gray);
		            	 break;
		             case 8:
		            	 gl2.glColor3f(1.0F*this.objectshading[x][y][z]*gray,1.0F*this.objectshading[x][y][z]*gray,1.0F*this.objectshading[x][y][z]*gray);
		            	 break;
		             case 9:
		            	 gl2.glColor3f(1.0F*this.objectshading[x][y][z]*gray,0.0F*this.objectshading[x][y][z]*gray,0.0F*this.objectshading[x][y][z]*gray);
		            	 break;
		             case 10:
		            	 gl2.glColor3f(1.0F*this.objectshading[x][y][z]*gray,1.0F*this.objectshading[x][y][z]*gray,0.0F*this.objectshading[x][y][z]*gray);
		            	 break;
		            }
		            if(this.getBlock(x,y,z+1)==0) { renderBlock(gl2,1,x,y,z, 0F,0F,0F); }
		            if(this.getBlock(x,y,z-1)==0) { renderBlock(gl2,2,x,y,z, 0F,0F,0F); }
				 	if(this.getBlock(x,y+1,z)==0) { renderBlock(gl2,3,x,y,z, 0F,0F,0F); }
				 	if(this.getBlock(x,y-1,z)==0) { renderBlock(gl2,4,x,y,z, 0F,0F,0F); }
				 	if(this.getBlock(x+1,y,z)==0) { renderBlock(gl2,5,x,y,z, 0F,0F,0F); }
				 	if(this.getBlock(x-1,y,z)==0) { renderBlock(gl2,6,x,y,z, 0F,0F,0F); }
					
				 }
			} } }
			gl2.glEndList();
			init = false;
		}
		gl2.glRotatef(this.rot_x, 1.0F, 0.0F, 0.0F);
	    gl2.glRotatef(this.rot_y, 0.0F, 1.0F, 0.0F);
	    gl2.glRotatef(this.rot_z, 0.0F, 0.0F, 1.0F);
	    gl2.glTranslatef(this.posX,this.posY,this.posZ);
		if(scale) {
			gl2.glScalef(0.5F,0.5F,0.5F);
		}
		gl2.glCallList(this.list);
	}
	
	public void renderBlock(GL2 gl2, int side, float x, float y, float z, float x2, float y2, float z2) {
		gl2.glPushMatrix();
		gl2.glTranslatef(x,y,z);
	    switch(side) {
		 case 1:
		 gl2.glBegin(GL2.GL_QUADS);
		 gl2.glTexCoord2f(0.0F,0.0F);
		 gl2.glVertex3f(0.0F, 0.0F, 1.0F);
		 gl2.glTexCoord2f(1.0F,0.0F);
		 gl2.glVertex3f(1.0F, 0.0F, 1.0F);
		 gl2.glTexCoord2f(1.0F,1.0F);
		 gl2.glVertex3f(1.0F, 1.0F, 1.0F);
		 gl2.glTexCoord2f(0.0F,1.0F);
		 gl2.glVertex3f(0.0F, 1.0F, 1.0F);
	     gl2.glEnd();
	     gl2.glPopMatrix();
	     return;
	     
		 case 2:
	     gl2.glBegin(GL2.GL_QUADS);
	     gl2.glTexCoord2f(0.0F,0.0F);
	     gl2.glVertex3f(1.0F, 0.0F, 0.0F);
	     gl2.glTexCoord2f(1.0F,0.0F);
	     gl2.glVertex3f(0.0F, 0.0F, 0.0F);
	     gl2.glTexCoord2f(1.0F,1.0F);
	     gl2.glVertex3f(0.0F, 1.0F, 0.0F);
	     gl2.glTexCoord2f(0.0F,1.0F);
	     gl2.glVertex3f(1.0F, 1.0F, 0.0F);
	     gl2.glEnd();
	     gl2.glPopMatrix();
	     return;

		 case 3:
	     gl2.glBegin(GL2.GL_QUADS);
	     gl2.glTexCoord2f(0.0F,0.0F);
	     gl2.glVertex3f(0.0F, 1.0F, 0.0F);
	     gl2.glTexCoord2f(1.0F,0.0F);
	     gl2.glVertex3f(0.0F, 1.0F, 1.0F);
	     gl2.glTexCoord2f(1.0F,1.0F);
	     gl2.glVertex3f(1.0F, 1.0F, 1.0F);
	     gl2.glTexCoord2f(0.0F,1.0F);
	     gl2.glVertex3f(1.0F, 1.0F, 0.0F);
	     gl2.glEnd();
	     gl2.glPopMatrix();
	     return;

		 case 4:
	     gl2.glBegin(GL2.GL_QUADS);
	     gl2.glTexCoord2f(0.0F,0.0F);
	     gl2.glVertex3f(1.0F, 0.0F, 1.0F);
	     gl2.glTexCoord2f(1.0F,0.0F);
	     gl2.glVertex3f(0.0F, 0.0F, 1.0F);
	     gl2.glTexCoord2f(1.0F,1.0F);
	     gl2.glVertex3f(0.0F, 0.0F, 0.0F);
	     gl2.glTexCoord2f(0.0F,1.0F);
	     gl2.glVertex3f(1.0F, 0.0F, 0.0F);
	     gl2.glEnd();
	     gl2.glPopMatrix();
	     return;

		 case 5:
	     gl2.glRotatef(90.0F,0.0F,0.0F,1.0F);
	     gl2.glTranslatef(0.0F,-1.0F,0.0F);

	     gl2.glBegin(GL2.GL_QUADS);
	     gl2.glTexCoord2f(0.0F,0.0F);
	     gl2.glVertex3f(1.0F, 0.0F, 1.0F);
	     gl2.glTexCoord2f(1.0F,0.0F);
	     gl2.glVertex3f(0.0F, 0.0F, 1.0F);
	     gl2.glTexCoord2f(1.0F,1.0F);
	     gl2.glVertex3f(0.0F, 0.0F, 0.0F);
	     gl2.glTexCoord2f(0.0F,1.0F);
	     gl2.glVertex3f(1.0F, 0.0F, 0.0F);
	     gl2.glEnd();
	     gl2.glPopMatrix();
	     return;

		 case 6:
	     gl2.glRotatef(90.0F,0.0F,0.0F,1.0F);
	     gl2.glTranslatef(0.0F,-1.0F,0.0F);
	     gl2.glRotatef(180.0F,1.0F,0.0F,0.0F);
	     gl2.glTranslatef(0.0F,-1.0F,-1.0F);

	     gl2.glBegin(GL2.GL_QUADS);
	     gl2.glTexCoord2f(0.0F,0.0F);
	     gl2.glVertex3f(1.0F, 0.0F, 1.0F);
	     gl2.glTexCoord2f(1.0F,0.0F);
	     gl2.glVertex3f(0.0F, 0.0F, 1.0F);
	     gl2.glTexCoord2f(1.0F,1.0F);
	     gl2.glVertex3f(0.0F, 0.0F, 0.0F);
	     gl2.glTexCoord2f(0.0F,1.0F);
	     gl2.glVertex3f(1.0F, 0.0F, 0.0F);
	     gl2.glEnd();
	     gl2.glPopMatrix();
	     return;
		}
	 }
}
