using UnityEngine;
using System.Collections;

public class CameraMovement : MonoBehaviour {

    // Camera, player and floor.
	private GameObject player;
	private Camera cam;
	private BoxCollider floor;
	
    // Margins and other camera stuff.
    private Vector3 offset;
    private float initx, initz;
	private double sizex, sizez;
	private Vector2 margin;
	private Vector2 marginXlvl;
	private Vector2 marginZlvl;
    private Vector3 pos;

    // Initial depth of camera.
    private int minDepth = 50;
    private int initialDepth;
    private int maxDepth = 100;

    // Value used to know what exit has used last the player. External relevance.
    public int auxExit = 0;
	

	void Awake() {
        // Camera definition.
		this.cam = (Camera) GetComponent<Camera>();
        this.initialDepth = minDepth;
        this.cam.fieldOfView = initialDepth;

        // Finding the player (the camera will follow him)
        this.player = GameObject.Find ("PlayerBody");
        
        this.offset = this.cam.transform.position;		// Offset camera position
        this.margin = new Vector2(4.0f, 4.0f);			// Margin for camera bounds
        this.marginXlvl = Vector2.zero;
		this.marginZlvl = this.marginXlvl;


        // If the tmp is not null...
        if (LoadSavePlayerStats.tmp != null) {
            // and is loading game, the player is coming from a loadGame.
            if (LoadSavePlayerStats.isLoaded) {
                this.setPlane(this.player.GetComponent<Player>().playerStats.floor);

            }

            // Else, is coming from a change of scene.
            else {
                this.setPlane(ChangingPlane.getPlane(Application.loadedLevelName, auxExit));
            }
            
        }

        // If the tmp is null, the player is coming from a new game.
        else {
            this.setPlane(ChangingPlane.getInitPlane());
        }
        
	}

    // Set the camera bounds depending of the floor's bos collider.
	public void setPlane(string name) {
		// Box Collider from a plane. 
        Debug.Log("Searching plane " + name);
		this.floor = GameObject.Find (name).GetComponent<BoxCollider>();

		// Setting the margins of the camera movement.
		this.limitPlane (floor);
	}

	// Calculate the margins of the camera movement.
	private void limitPlane(BoxCollider fl){

		// If the BoxCollider is not null, reassignment is produced.
        if (fl != null) {
            Debug.Log("Floor is not null.");
            this.floor = fl;
        } 

		// If the margin of the camera is bigger than the size x of the plane,
		// the camera won't move on it and its margin movemente will be the center
		// of the plane. Otherwise, there will be a little window of movement.
		//Debug.Log ("Margins: " + (this.margin [0] + this.margin [1]));
		//Debug.Log ("Floor X bounds: " + this.floor.bounds.size.x);
		//Debug.Log ("Floor Z bounds: " + this.floor.bounds.size.z);

		if ((this.margin [0] + this.margin [1]) < this.floor.bounds.size.x) {
			float minx, maxx;
			minx = this.floor.bounds.min.x + this.margin[0];
			maxx = this.floor.bounds.max.x - this.margin[0];
			this.marginXlvl[0] = minx;
			this.marginXlvl[1] = maxx;			
		} else {
			this.marginXlvl[0] = this.floor.bounds.center.x;
			this.marginXlvl[1] = this.marginXlvl[0];
		}

		// The same in the z-axis.
		if (this.margin [0] + this.margin [1] < this.floor.bounds.size.z) {
			float minz, maxz;
			minz = this.floor.bounds.min.z + this.margin[1];
			maxz = this.floor.bounds.max.z - this.margin[1];
			this.marginZlvl[0] = minz;
			this.marginZlvl[1] = maxz;
		} else {
			this.marginZlvl[0] = this.floor.bounds.center.z;
			this.marginZlvl[1] = this.marginZlvl[0];
		}

		//Debug.Log ("MarginsX: " + (this.marginXlvl [0] + "," + this.marginXlvl [1]));
	    //Debug.Log ("MarginsZ: " + (this.marginZlvl [0] + "," + this.marginZlvl [1]));
	}

	// Called once per frame after update.
	void LateUpdate() {
        if (this.player == null) return;
        
        // Transition 
	    if (this.player.GetComponent<PlayerMovement> ().transition ) {
			this.cam.transform.position = Vector3.MoveTowards 
                                                          (this.cam.transform.position,
			                                               this.player.transform.position,
			                                               Time.deltaTime);
			return;
		}


		// This should be the new position of the camera, but...
        Vector3 pos = this.player.transform.position + offset;

		// Finally, the camera movement will be:
        this.cam.transform.position = AdjustCamera(pos);

        // Updates the field of view of the camera with the wheel mouse.
        cam.fieldOfView += Input.GetAxis("Mouse ScrollWheel") * (-15);
        cam.fieldOfView = Mathf.Clamp(cam.fieldOfView, minDepth, maxDepth);

	}

    // Called in every update, moves the camera following the player and respecting
    // the bounds of the floor.
    private Vector3 AdjustCamera(Vector3 pos) {
        float x, z;

        // If the new location is inside the margin, cool. If not, it need to be placed
        // on the same place. In X-axis. 
        //Debug.Log("FL: " + floor + " POS: " + pos + " MX: " + marginXlvl + " MZ: " + marginZlvl);
       
        if (pos.x >= this.marginXlvl[0] && pos.x <= this.marginXlvl[1]) {
            x = pos.x;
        } else {
            if (pos.x < this.marginXlvl[0]) {
                x = this.marginXlvl[0];
            } else if (pos.x > this.marginXlvl[1]) {
                x = this.marginXlvl[1];
            } else {
                x = this.cam.transform.position.x;
            }            
        }

        // Same as above, but for Z-axis.
        if (pos.z >= this.marginZlvl[0] && pos.z <= this.marginZlvl[1])
        {
            z = pos.z;
        }
        else
        {
            if (pos.z < this.marginZlvl[0]) {
                z = this.marginZlvl[0];
            } else if (pos.z > this.marginZlvl[1]) {
                z = this.marginZlvl[1];
            } else {
                z = this.cam.transform.position.z;
            }

        }

        // New position!
        return new Vector3(x, pos.y, z);
    }
}