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

public struct block {
	
	public int x;
	public int y;

	public wallType type;

	public block(int x, int y, wallType type) 
	{
		this.x = x;
		this.y = y;
		this.type = type;
	}

}

[System.Serializable]
public struct generationData {

	public string name;

	[Range(0,100)]
	public float heightVariation;

	[Range(0,100)]
	public float holeDensity;

	[Range(0,100)]
	public float colorDensity;

	[Range(0,10)]
	public int colorLength;

	[Range(0,1)]
	public float greenColorWeighting;

	[Range(0,100)]
	public float filterChange;

	[Range(0,10)]
	public int filterMinimunDistance;

	[Range(0,1)]
	public float greenFilterWeighting;

	public int areaLength;

}

public class mapGenerator : MonoBehaviour {

	//publics
	public Sprite neutral;
	public Sprite green;
	public Sprite orange;
	public Sprite deadly;

	public Transform greenFilter;
	public Transform orangeFilter;

	public Transform player;
	public Transform genericBlock;


	//level data
	public generationData data;
	public generationData[] levels;

	public int levelLength = 30;

	//ground settings
	private int groundMaximum = 4; 
	private int groundMinimun = -6;
	private int groundLevel = -5;


	//premade blocks
	private Transform[] blockRoster = new Transform[500];
	private int blockInt = 0;


	//blockmap
	private List<block> blocks = new List<block>();
	private Transform t;


	//level progress
	private int level = 0;
	private int levelChangeAt = 0;
	private int currentProgress = 0;

	private int currentLimit = 0;


	// Use this for initialization
	void Start () {

		//first area change
		levelChangeAt = data.areaLength;

		//pre made tiles to be used for level..
		makeBlockRoster ();

		generateBlockmap ();
		makeBlocks ();
		blocks.Clear ();
		currentLimit += levelLength;

		t = transform;
	}

	void Update() {

		//create next chunk of terrain 
		if (player.position.x > currentLimit - 30)
			generateMoreLevel ();

	}

	void makeBlockRoster() {

		for (int n = 0; n < 400 ;n++) {
			Transform b = Instantiate(genericBlock, Vector3.up*100, Quaternion.identity) as Transform;
			b.parent = t;
			blockRoster[n] = b;

		}

	}

	public void generateMoreLevel() {

		//when progress passes the end of area, start using variables from next levels-node
		currentProgress++;
		if (currentProgress == levelChangeAt) {

			data = levels[level];
			levelChangeAt += data.areaLength;
			level++;
		}

		generateBlockmap ();
		makeBlocks ();
		blocks.Clear ();

		currentLimit += levelLength;

	}

	void makeBlocks() {

		Vector3 pos = Vector3.zero;

		foreach (block b in blocks) {

			pos.x = b.x + currentLimit;
			pos.y = b.y;

			blockInt++;
			if (blockInt > 399) blockInt = 0;

			blockRoster[blockInt].position = pos;

			switch(b.type) {
			case wallType.neutral:
				blockRoster[blockInt].GetComponent<SpriteRenderer>().sprite = neutral;
				blockRoster[blockInt].GetComponent<wallBehaviour>().type = wallType.neutral;
				break;
			case wallType.green:
				blockRoster[blockInt].GetComponent<SpriteRenderer>().sprite = green;
				blockRoster[blockInt].GetComponent<wallBehaviour>().type = wallType.green;
				break;
			case wallType.orange:
				blockRoster[blockInt].GetComponent<SpriteRenderer>().sprite = orange;
				blockRoster[blockInt].GetComponent<wallBehaviour>().type = wallType.orange;	
				break;
			case wallType.deadly:
					
				break;
			}

		}
	}

	void generateBlockmap() {

		//make ground
		int holes = 0; //is making hole for next n areas
		int greenArea = 0; //is making green floor
		int orangeArea = 0; //is making orange floor
		int lastFilter = -1; //distance to previous filter, prevents creating impossible double filters

		for (int x = 0; x < levelLength; x += 2) {

			//if making hole, dont create area at all
			if (holes < 1) {
				for (int y = groundLevel; y >= groundMinimun-2; y -= 2) {

					//make colored floors..
					if (orangeArea > 0 && y == groundLevel) {
						blocks.Add(new block(x,y,wallType.orange));
					} else {
						if (greenArea > 0 && y == groundLevel) {
							blocks.Add(new block(x,y,wallType.green));
						} else {
							blocks.Add(new block(x,y,wallType.neutral));
						}
					}
				}	

				//randomly change floor height sometimes
				if (data.heightVariation > Random.Range(0,100)) {
					
					groundLevel = groundLevel - 4 + (int)Random.Range(0,9);
					
					if (groundLevel < groundMinimun) groundLevel = groundMinimun;
					if (groundLevel > groundMaximum) groundLevel = groundMaximum;
				}

				//sometimes add holes
				if (data.holeDensity > Random.Range(0,100)) holes = 2 + (int)(Random.value * 2);

				//sometimes add colored areas
				//if (orangeArea < 0 && greenArea < 0) {
					if (data.colorDensity > Random.Range(0,100)) {
						if (Random.value < data.greenColorWeighting) {
							greenArea = 2 + (int)(Random.value * data.colorLength);
						} else {
							orangeArea = 2 + (int)(Random.value * data.colorLength);
						}

					}
				//}

				//sometimes add filters
				lastFilter++;
				if (lastFilter > data.filterMinimunDistance && Random.Range(0,100) < data.filterChange) {
					lastFilter = 0;
					if (Random.value < data.greenFilterWeighting) {
						Instantiate(greenFilter, new Vector3(currentLimit+x,0,2), Quaternion.identity);
					} else {
						Instantiate(orangeFilter, new Vector3(currentLimit+x,0,2), Quaternion.identity);
					}
				}

			} else {

				holes--;
			}

			greenArea--;
			orangeArea--;

		}

	}
}











