using UnityEngine;
using System.Collections;

public class CameraController : MonoBehaviour {

    public Transform player;
    public Vector2 margin;
    public Vector2 smoothing;
    public float maxOrthographicSize;
    public float minOrthographicSize;
    public float expandCoefficient;
    public float shrinkCoefficient;
    public BoxCollider2D bounds;
    private Vector3 min;
    private Vector3 max;

    private const float CAMERA_ROTATION_PERCENT = 0.3f;
    private const float DEFAULT_GRAVITY_ANGLE = 360;

    public bool isFollowing { get; set; }

    void Start() {
        isFollowing = true;
        min = bounds.bounds.min;
        max = bounds.bounds.max;
    }
    
    void Update() {
        var x = transform.position.x;
        var y = transform.position.y;

        applyScreenRotation();

        if (isFollowing) {

            updateOrthographicSize();

            // make sure x coordinate is within margin
            if (Mathf.Abs(x - player.position.x) > margin.x) {
                x = Mathf.Lerp(x, player.position.x, smoothing.x * Time.deltaTime);
            }

            // make sure y coordinate is within margin
            if (Mathf.Abs(y - player.position.y) > margin.y) {
                y = Mathf.Lerp(y, player.position.y, smoothing.y * Time.deltaTime);
            }
        }


        var cameraHalfWidth = camera.orthographicSize * ((float) Screen.width / Screen.height);

        // Clamp that shit
        x = Mathf.Clamp(x, min.x + cameraHalfWidth, max.x - cameraHalfWidth);
        y = Mathf.Clamp(y, min.y + camera.orthographicSize, max.y - camera.orthographicSize);

        transform.position = new Vector3(x, y, transform.position.z);

    }

    private void applyScreenRotation() {
        float currentGravity = PlayerController.caluateAngle(Physics2D.gravity);
        float gravityDelta = currentGravity - DEFAULT_GRAVITY_ANGLE;

        float adjustedGravity = DEFAULT_GRAVITY_ANGLE + (gravityDelta * CAMERA_ROTATION_PERCENT);

        Quaternion targetRotation = Quaternion.Euler(transform.rotation.z, transform.rotation.y, adjustedGravity);
        transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2);
    }

    /**
     * Purpose of function if to expand/contract camera such that
     *   when hero is not grounded, camera focus gets bigger
     *        hero is grounded, camera focus contracts
     * TODO: adjust behaviour such that any movement is trigger
     */
    private void updateOrthographicSize() {
        PlayerController playerController = GameObject.Find("hero_idle").GetComponent<PlayerController>();
        Vector3 direction = playerController.GroundedDirection();

        // get bigger
        if (direction.y >= 0 && camera.orthographicSize <= maxOrthographicSize) {
            camera.orthographicSize = Mathf.Lerp(
                camera.orthographicSize,
                camera.orthographicSize * expandCoefficient,
                smoothing.y * Time.deltaTime
                );
        }

        // get smaller
        if (direction.y < 0 && camera.orthographicSize >= minOrthographicSize) {
            camera.orthographicSize = Mathf.Lerp(
                camera.orthographicSize,
                camera.orthographicSize * shrinkCoefficient,
                smoothing.y * Time.deltaTime);
        }

        // clamp that shit
        camera.orthographicSize = Mathf.Clamp(camera.orthographicSize, minOrthographicSize, maxOrthographicSize);
    }
}
