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

public class CameraController : MonoBehaviour {

    [Header("General Settings")]
    public bool rotateDir;
    public bool zoomDir;
    public int edgeDist;

    [Header("Zooming Settings")]
    public float minZoom;
    public float maxZoom;
    public float minMoveSpeed;
    public float maxMoveSpeed;
    public float minRotateSpeed;
    public float maxRotateSpeed;
    public float minDist;
    public float maxDist;

    private GameObject cam;

    private Rect screenBounds;
    private Rect curRes;

    [SerializeField]
    private float curZoom;
    
    private float zoomPercent {
        get
        {
            return Mathf.Clamp01(curZoom / maxZoom);
        }
    }


    public void Start()
    {
        CalculateScreenBounds();

        Debug.Assert(minZoom < maxZoom);
        curZoom = maxZoom;

        cam = Camera.main.gameObject;
    }

    public void Update()
    {
        Rect newScreen = new Rect(0, 0, Screen.width, Screen.height);
        if (curRes.width != newScreen.width || curRes.height != newScreen.height)
            CalculateScreenBounds();
    }

    public void LateUpdate()
    {
        //Handle Zoom
        float scroll = Input.mouseScrollDelta.y;
        if (zoomDir) scroll *= -1f;
        curZoom = Mathf.Clamp(curZoom + scroll, minZoom, maxZoom);

        Vector3 newDist = cam.transform.localPosition;
        newDist.z = Mathf.Clamp(Mathf.Lerp(minDist, maxDist, zoomPercent), minDist, maxDist);
        cam.transform.localPosition = newDist;

        Vector2 input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
        float rInput = Input.GetAxis("Rotation");

        Vector3 eulerDelta = Vector3.zero;
        eulerDelta.y = rInput;
        if (rotateDir)
            eulerDelta *= -1f;

        Vector3 translationDelta = Vector3.zero;
        translationDelta.x = input.x;
        translationDelta.z = input.y;

        Vector2 mousePos = Input.mousePosition;
        if (!screenBounds.Contains(mousePos))
        {
            Vector3 localMoveDir = EdgeMoveDir(mousePos);
            if (localMoveDir != Vector3.zero)
                translationDelta = localMoveDir;
        }

        if (translationDelta.magnitude > 0f)
            translationDelta.Normalize();

        float curMoveSpeed = Mathf.Lerp(minMoveSpeed, maxMoveSpeed, zoomPercent);
        float curRotateSpeed = Mathf.Lerp(minRotateSpeed, maxRotateSpeed, zoomPercent);

        transform.Translate(translationDelta * Time.deltaTime * curMoveSpeed);
        transform.Rotate(eulerDelta * Time.deltaTime * curRotateSpeed);
    }

    private void CalculateScreenBounds()
    {
        curRes = new Rect(0, 0, Screen.width, Screen.height);
        screenBounds.xMin = edgeDist;
        screenBounds.yMin = edgeDist;
        screenBounds.xMax = Screen.width - edgeDist;
        screenBounds.yMax = Screen.height - edgeDist;
    }

    private Vector3 EdgeMoveDir(Vector2 mousePos)
    {
        Vector3 ret = Vector3.zero;
        if (mousePos.y >= screenBounds.yMax)
            ret += Vector3.forward;
        if (mousePos.y <= screenBounds.yMin)
            ret += -Vector3.forward;
        if (mousePos.x <= screenBounds.xMin)
            ret += -Vector3.right;
        if (mousePos.x >= screenBounds.xMax)
            ret += Vector3.right;
        return ret;
    }
}
