package coolbot;

import javax.media.opengl.GL;

import com.sun.opengl.util.texture.Texture;

import devUtil.TextureLoader;
import object.AutoHeightMap;

public class Landscape extends AutoHeightMap {
	
	protected Texture mountainTexture;
	protected Texture landTexture;
	
	protected Texture seaTexture;
	
	protected Texture wallTexture;
	
	double seaLevel;
	
	public Landscape() {
		
		mountainTexture = TextureLoader.getTexture("/visual/textures/Rocky.jpg");
		landTexture = TextureLoader.getTexture("/visual/textures/Sand.jpg");
		
		seaTexture = TextureLoader.getTexture("/visual/textures/Pool.jpg");
		
		wallTexture = TextureLoader.getTexture("/visual/textures/Rocky.jpg");
	}
	
	public void generate(int size, int diamondSquareIterations, int smoothness, double seaLevel) {

		super.generate(size, diamondSquareIterations, smoothness);
		
		this.seaLevel = lowestPoint + (highestPoint - lowestPoint) * seaLevel;
	}
	
	public double waveX;
	public double waveZ;
	
	public void render(GL gl, double width, double length, double height) {
		
		width /= map.length;
		length /= map[0].length;
		height /= highestPoint - lowestPoint;
		
		for(int x = 0; x < map.length - 2; x++)
			for(int z = 0; z < map.length - 2; z++) {
				
				if(map[x][z] < lowestPoint + (highestPoint - lowestPoint) * .75) {
					landTexture.enable();
					landTexture.bind();
				}
				
				else {
					mountainTexture.enable();
					mountainTexture.bind();
				}
				
				gl.glBegin(GL.GL_QUADS);
				
				setColor(gl, x, z);
				
				gl.glTexCoord2d(0, 0);
				
				gl.glVertex3d(
						(x * width) - ((width * map.length) / 2) + xPos,
						map[x][z] * height + yPos,
						(z * length) - ((length * map[0].length) / 2) + zPos
						);
				
				gl.glTexCoord2d(1, 0);
				
				gl.glVertex3d(
						(x * width) - ((width * map.length) / 2) + xPos,
						map[x][z + 1] * height + yPos,
						((z + 1) * length) - ((length * map[0].length) / 2) + zPos
						);
				
				gl.glTexCoord2d(1, 1);
				
				gl.glVertex3d(
						((x + 1) * width) - ((width * map.length) / 2) + xPos,
						map[x + 1][z + 1] * height + yPos,
						((z + 1) * length) - ((length * map[0].length) / 2) + zPos
						);
				
				gl.glTexCoord2d(0, 1);
				
				gl.glVertex3d(
						((x + 1) * width) - ((width * map.length) / 2) + xPos,
						map[x + 1][z] * height + yPos,
						(z * length) - ((length * map[0].length) / 2) + zPos
						);
				
				gl.glEnd();
			}
		
		// Water
		
		width *= map.length;
		length *= map[0].length;
		
		waveX += width / 5000;
		waveZ += length / 5000;
		
		if(waveX > width)
			waveX = 0;
		
		if(waveZ > width)
			waveZ = 0;
		
		seaTexture.enable();
		seaTexture.bind();
		
		// panel 1
		
		gl.glBegin(GL.GL_QUADS);
		
		gl.glTexCoord2d(0, 0);
		
		gl.glVertex3d(
				-(width / 2) + xPos - waveX,
				seaLevel * height + yPos,
				-(length / 2) + zPos - waveZ
				);
		
		gl.glTexCoord2d(1, 0);
		
		gl.glVertex3d(
				(width / 2) + xPos - waveX,
				seaLevel * height + yPos,
				-(length / 2) + zPos - waveZ
				);
		
		gl.glTexCoord2d(1, 1);
		
		gl.glVertex3d(
				(width / 2) + xPos - waveX,
				seaLevel * height + yPos,
				(length / 2) + zPos - waveZ
				);
		
		gl.glTexCoord2d(0, 1);
		
		gl.glVertex3d(
				-(width / 2) + xPos - waveX,
				seaLevel * height + yPos,
				(length / 2) + zPos - waveZ
				);
		
		gl.glEnd();
		
		// panel 2
		
		gl.glBegin(GL.GL_QUADS);
		
		gl.glTexCoord2d(0, 0);
		
		gl.glVertex3d(
				-(width / 2) + xPos + width - waveX,
				seaLevel * height + yPos,
				-(length / 2) + zPos - waveZ
				);
		
		gl.glTexCoord2d(1, 0);
		
		gl.glVertex3d(
				(width / 2) + xPos + width - waveX,
				seaLevel * height + yPos,
				-(length / 2) + zPos - waveZ
				);
		
		gl.glTexCoord2d(1, 1);
		
		gl.glVertex3d(
				(width / 2) + xPos + width - waveX,
				seaLevel * height + yPos,
				(length / 2) + zPos - waveZ
				);
		
		gl.glTexCoord2d(0, 1);
		
		gl.glVertex3d(
				-(width / 2) + xPos + width - waveX,
				seaLevel * height + yPos,
				(length / 2) + zPos - waveZ
				);
		
		gl.glEnd();
		
		// panel 3
		
		gl.glBegin(GL.GL_QUADS);
		
		gl.glTexCoord2d(0, 0);
		
		gl.glVertex3d(
				-(width / 2) + xPos + width - waveX,
				seaLevel * height + yPos,
				-(length / 2) + zPos + length - waveZ
				);
		
		gl.glTexCoord2d(1, 0);
		
		gl.glVertex3d(
				(width / 2) + xPos + width - waveX,
				seaLevel * height + yPos,
				-(length / 2) + zPos + length - waveZ
				);
		
		gl.glTexCoord2d(1, 1);
		
		gl.glVertex3d(
				(width / 2) + xPos + width - waveX,
				seaLevel * height + yPos,
				(length / 2) + zPos + length - waveZ
				);
		
		gl.glTexCoord2d(0, 1);
		
		gl.glVertex3d(
				-(width / 2) + xPos + width - waveX,
				seaLevel * height + yPos,
				(length / 2) + zPos + length - waveZ
				);
		
		gl.glEnd();
		
		// panel 4
		
		gl.glBegin(GL.GL_QUADS);
		
		gl.glTexCoord2d(0, 0);
		
		gl.glVertex3d(
				-(width / 2) + xPos - waveX,
				seaLevel * height + yPos,
				-(length / 2) + zPos + length - waveZ
				);
		
		gl.glTexCoord2d(1, 0);
		
		gl.glVertex3d(
				(width / 2) + xPos - waveX,
				seaLevel * height + yPos,
				-(length / 2) + zPos + length - waveZ
				);
		
		gl.glTexCoord2d(1, 1);
		
		gl.glVertex3d(
				(width / 2) + xPos - waveX,
				seaLevel * height + yPos,
				(length / 2) + zPos + length - waveZ
				);
		
		gl.glTexCoord2d(0, 1);
		
		gl.glVertex3d(
				-(width / 2) + xPos - waveX,
				seaLevel * height + yPos,
				(length / 2) + zPos + length - waveZ
				);
		
		gl.glEnd();
		
		// Walls
		
		wallTexture.enable();
		wallTexture.bind();
		
		// wall 1
		
		gl.glBegin(GL.GL_QUADS);
		
		gl.glTexCoord2d(0, 0);
		
		gl.glVertex3d(
				-(width / 2) + xPos,
				lowestPoint * height + yPos,
				-(length / 2) + zPos
				);
		
		gl.glTexCoord2d(1, 0);
		
		gl.glVertex3d(
				-(width / 2) + xPos,
				highestPoint * height + yPos,
				-(length / 2) + zPos
				);
		
		gl.glTexCoord2d(1, 1);
		
		gl.glVertex3d(
				-(width / 2) + xPos,
				highestPoint * height + yPos,
				(length / 2) + zPos
				);
		
		gl.glTexCoord2d(0, 1);
		
		gl.glVertex3d(
				-(width / 2) + xPos,
				lowestPoint * height + yPos,
				(length / 2) + zPos
				);
		
		gl.glEnd();
		
		// wall 2
		
		gl.glBegin(GL.GL_QUADS);
		
		gl.glTexCoord2d(0, 0);
		
		gl.glVertex3d(
				-(width / 2) + xPos,
				lowestPoint * height + yPos,
				-(length / 2) + zPos
				);
		
		gl.glTexCoord2d(1, 0);
		
		gl.glVertex3d(
				-(width / 2) + xPos,
				highestPoint * height + yPos,
				-(length / 2) + zPos
				);
		
		gl.glTexCoord2d(1, 1);
		
		gl.glVertex3d(
				(width / 2) + xPos,
				highestPoint * height + yPos,
				-(length / 2) + zPos
				);
		
		gl.glTexCoord2d(0, 1);
		
		gl.glVertex3d(
				(width / 2) + xPos,
				lowestPoint * height + yPos,
				-(length / 2) + zPos
				);
		
		gl.glEnd();
		
		// wall 3
		
		gl.glBegin(GL.GL_QUADS);
		
		gl.glTexCoord2d(0, 0);
		
		gl.glVertex3d(
				(width / 2) + xPos,
				lowestPoint * height + yPos,
				-(length / 2) + zPos
				);
		
		gl.glTexCoord2d(1, 0);
		
		gl.glVertex3d(
				(width / 2) + xPos,
				highestPoint * height + yPos,
				-(length / 2) + zPos
				);
		
		gl.glTexCoord2d(1, 1);
		
		gl.glVertex3d(
				(width / 2) + xPos,
				highestPoint * height + yPos,
				(length / 2) + zPos
				);
		
		gl.glTexCoord2d(0, 1);
		
		gl.glVertex3d(
				(width / 2) + xPos,
				lowestPoint * height + yPos,
				(length / 2) + zPos
				);
		
		gl.glEnd();
		
		// wall 4
		
		gl.glBegin(GL.GL_QUADS);
		
		gl.glTexCoord2d(0, 0);
		
		gl.glVertex3d(
				(width / 2) + xPos,
				lowestPoint * height + yPos,
				(length / 2) + zPos
				);
		
		gl.glTexCoord2d(1, 0);
		
		gl.glVertex3d(
				(width / 2) + xPos,
				highestPoint * height + yPos,
				(length / 2) + zPos
				);
		
		gl.glTexCoord2d(1, 1);
		
		gl.glVertex3d(
				-(width / 2) + xPos,
				highestPoint * height + yPos,
				(length / 2) + zPos
				);
		
		gl.glTexCoord2d(0, 1);
		
		gl.glVertex3d(
				-(width / 2) + xPos,
				lowestPoint * height + yPos,
				(length / 2) + zPos
				);
		
		gl.glEnd();
		
		mountainTexture.disable();
		landTexture.disable();
		
		seaTexture.disable();
		
		wallTexture.disable();
	}
	
	public double getSeaLevel(double height) {
		return seaLevel * (height / (highestPoint - lowestPoint)) + yPos;
	}
	
	public double getMountainLevel(double height) {
		return .75 * (height / (highestPoint - lowestPoint)) + yPos;
	}
}