﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Chunk : MonoBehaviour {

	private List<Vector3> newVertices = new List<Vector3>();
	private List<int> newTriangles = new List<int>();
	private List<Vector2> newUV = new List<Vector2>();

	public GameObject worldGO;
	private World world;

	private float tUnit = 0.25f;
	private Vector2 tStone = new Vector2(1,0);
	private Vector2 tGrass = new Vector2(0,1);
	private Vector2 tGrassTop = new Vector2(1,1);

	private Mesh mesh;
	private MeshCollider col;

	public bool update;

	private int faceCount;

	public int chunkSize = 16;

	public int chunkX;
	public int chunkY;
	public int chunkZ;

	// Use this for initialization
	void Start () {
		mesh = GetComponent<MeshFilter> ().mesh;

		col = GetComponent<MeshCollider> ();

		world = worldGO.GetComponent ("World") as World;
		GenerateMesh ();

	}
	
	// Update is called once per frame
	void Update () {
	
	}

	void CubeTop(int x, int y, int z, byte block) {

		newVertices.Add(new Vector3 (x,  y,  z + 1));
		newVertices.Add(new Vector3 (x + 1, y,  z + 1));
		newVertices.Add(new Vector3 (x + 1, y,  z ));
		newVertices.Add(new Vector3 (x,  y,  z ));
		
		Vector2 texturePos = new Vector2(0,0);
		if (Block (x, y, z) == 1) {
			texturePos = tStone;
		} else if (Block (x, y, z) == 2) {
			texturePos = tGrassTop;
		}

		Cube (texturePos);

	}

	void CubeNorth(int x, int y, int z, byte block) {
		
		newVertices.Add(new Vector3 (x + 1, y-1, z + 1));
		newVertices.Add(new Vector3 (x + 1, y, z + 1));
		newVertices.Add(new Vector3 (x, y, z + 1));
		newVertices.Add(new Vector3 (x, y-1, z + 1));
		
		Vector2 texturePos = new Vector2(0,0);
		
		if(Block(x,y,z)==1){
			texturePos=tStone;
		} else if(Block(x,y,z)==2){
			texturePos=tGrass;
		}
		
		Cube (texturePos);
		
	}
	void CubeEast(int x, int y, int z, byte block) {
		
		newVertices.Add(new Vector3 (x + 1, y - 1, z));
		newVertices.Add(new Vector3 (x + 1, y, z));
		newVertices.Add(new Vector3 (x + 1, y, z + 1));
		newVertices.Add(new Vector3 (x + 1, y - 1, z + 1));
		
		Vector2 texturePos = new Vector2(0,0);
		
		if(Block(x,y,z)==1){
			texturePos=tStone;
		} else if(Block(x,y,z)==2){
			texturePos=tGrass;
		}
		
		Cube (texturePos);
		
	}
	void CubeSouth(int x, int y, int z, byte block) {
		
		newVertices.Add(new Vector3 (x, y - 1, z));
		newVertices.Add(new Vector3 (x, y, z));
		newVertices.Add(new Vector3 (x + 1, y, z));
		newVertices.Add(new Vector3 (x + 1, y - 1, z));
		
		Vector2 texturePos = new Vector2(0,0);
		
		if(Block(x,y,z)==1){
			texturePos=tStone;
		} else if(Block(x,y,z)==2){
			texturePos=tGrass;
		}
		
		Cube (texturePos);
		
	}
	void CubeWest(int x, int y, int z, byte block) {
		
		newVertices.Add(new Vector3 (x, y- 1, z + 1));
		newVertices.Add(new Vector3 (x, y, z + 1));
		newVertices.Add(new Vector3 (x, y, z));
		newVertices.Add(new Vector3 (x, y - 1, z));
		
		Vector2 texturePos = new Vector2(0,0);
		
		if(Block(x,y,z)==1){
			texturePos=tStone;
		} else if(Block(x,y,z)==2){
			texturePos=tGrass;
		}
		
		Cube (texturePos);
		
	}

	void CubeBottom(int x, int y, int z, byte block) {
		
		newVertices.Add(new Vector3 (x,  y-1,  z ));
		newVertices.Add(new Vector3 (x + 1, y-1,  z ));
		newVertices.Add(new Vector3 (x + 1, y-1,  z + 1));
		newVertices.Add(new Vector3 (x,  y-1,  z + 1));
		
		Vector2 texturePos = new Vector2(0,0);
		
		if(Block(x,y,z)==1){
			texturePos=tStone;
		} else if(Block(x,y,z)==2){
			texturePos=tGrass;
		}
		
		Cube (texturePos);
		
	}

	void Cube(Vector2 texturePos) {

		newTriangles.Add(faceCount * 4  ); //1
		newTriangles.Add(faceCount * 4 + 1 ); //2
		newTriangles.Add(faceCount * 4 + 2 ); //3
		newTriangles.Add(faceCount * 4  ); //1
		newTriangles.Add(faceCount * 4 + 2 ); //3
		newTriangles.Add(faceCount * 4 + 3 ); //4

		newUV.Add(new Vector2 (tUnit * texturePos.x + tUnit, tUnit * texturePos.y));
		newUV.Add(new Vector2 (tUnit * texturePos.x + tUnit, tUnit * texturePos.y + tUnit));
		newUV.Add(new Vector2 (tUnit * texturePos.x, tUnit * texturePos.y + tUnit));
		newUV.Add(new Vector2 (tUnit * texturePos.x, tUnit * texturePos.y));

		faceCount++;
	
	}

	void UpdateMesh() {
		mesh.Clear ();
		mesh.vertices = newVertices.ToArray ();
		mesh.uv = newUV.ToArray ();
		mesh.triangles = newTriangles.ToArray ();
		mesh.Optimize ();
		mesh.RecalculateNormals ();
		col.sharedMesh = null;
		col.sharedMesh = mesh;

		newVertices.Clear ();
		newUV.Clear ();
		newTriangles.Clear ();

		faceCount = 0;



	}

public void GenerateMesh() {

		for(int x = 0; x<chunkSize; x++) {
			for(int y = 0; y<chunkSize; y++) {
				for(int z = 0; z<chunkSize; z++) {

					if(Block(x,y,z)!=0) {

						if(Block(x,y+1,z) == 0) {
							CubeTop(x,y,z,Block (x,y,z));
						}

						if(Block(x,y-1,z)==0) {
							CubeBottom(x,y,z,Block (x,y,z));
						}

						if(Block (x+1,y,z)==0) {
							CubeEast(x,y,z,Block (x,y,z));
						}

						if(Block(x-1,y,z)==0) {
							CubeWest(x,y,z,Block(x,y,z));
						}

						if(Block(x,y,z+1)==0) {
							CubeNorth(x,y,z,Block(x,y,z));
						}

						if(Block(x,y,z-1)==0) {
							CubeSouth(x,y,z,Block(x,y,z));
						}

					}

				}
			}
		}
		UpdateMesh();
	}

	byte Block(int x, int y, int z) {
		return world.Block(x+chunkX,y+chunkY,z+chunkZ);
	}

	void LateUpdate() {

		if (update) {
			GenerateMesh();
			update=false;
		}

	}
}
