﻿using UnityEngine;
using System.Collections;

namespace Nostalgia.Example
{
	[AddComponentMenu("Nostalgia/Example/CameraController")]
	public sealed class CameraController : MonoBehaviour
	{
		public Transform target;
		public Stage stage;
		public float smoothTime = 0.1f;

		public Vector2 captureArea = new Vector2( 0.0f,0.5f );

		enum FollowMode
		{
			None,
			Normal,
			Smooth,
		}

		Vector3 _BasePosition;
		Vector3 _FirstBackgroundPos;

		Camera _CachedCamera;
		Camera cachedCamera
		{
			get
			{
				if (_CachedCamera == null)
				{
					_CachedCamera = GetComponent<Camera>();
				}
				return _CachedCamera;
			}
		}
		
		public void Initialize(Stage stage)
		{
			this.stage = stage;

			ClampPosition(stage.mainMap.transform.position);

			cachedCamera.backgroundColor = stage.backgroundColor;

			_BasePosition = transform.position;
			if (stage.background != null)
			{
				_FirstBackgroundPos = stage.background.transform.position;
			}

			UpdatePosition(FollowMode.Normal);
		}

		void UpdatePosition(FollowMode followMode)
		{
			if (target == null)
			{
				return;
			}

			if (followMode != FollowMode.None)
			{
				Vector2 extents = new Vector2(cachedCamera.aspect * cachedCamera.orthographicSize, cachedCamera.orthographicSize);

				Vector2 captureExtents = Vector2.Scale(extents, captureArea);

				Vector2 pos = transform.position;

				Vector2 move = (Vector2)target.position - pos;

				if (move.x >= captureExtents.x)
				{
					move.x -= captureExtents.x;
				}
				else if (move.x <= -captureExtents.x)
				{
					move.x += captureExtents.x;
				}
				else
				{
					move.x = 0.0f;
				}

				if (move.y >= captureExtents.y)
				{
					move.y -= captureExtents.y;
				}
				else if (move.y <= -captureExtents.y)
				{
					move.y += captureExtents.y;
				}
				else
				{
					move.y = 0.0f;
				}

				switch (followMode)
				{
					case FollowMode.Normal:
						pos += move;
						break;
					case FollowMode.Smooth:
						Vector2 velocity = Vector2.zero;
						pos = Vector2.SmoothDamp(pos, pos + move, ref velocity, smoothTime, Mathf.Infinity, Time.deltaTime);
						break;
				}

				ClampPosition(pos);
			}
		}

		void ClampPosition(Vector2 position)
		{
			if (stage != null && stage.mainMap)
			{
				Vector2 extents = new Vector2(cachedCamera.aspect * cachedCamera.orthographicSize, cachedCamera.orthographicSize);

				Vector2 mapPos = stage.mainMap.transform.position;

				Vector2 minArea = mapPos + extents;
				Vector2 maxArea = mapPos + new Vector2(stage.mainMap.width, stage.mainMap.height) - extents;

				position.x = Mathf.Clamp(position.x, minArea.x, maxArea.x);
				position.y = Mathf.Clamp(position.y, minArea.y, maxArea.y);
			}

			transform.position = new Vector3(position.x,position.y, transform.position.z);
		}
		
		void LateUpdate()
		{
			UpdatePosition(FollowMode.Smooth);

			if (stage != null && stage.background != null)
			{
				Vector3 moveBackground = (transform.position - _BasePosition) * stage.backgroundSpeed;

				stage.background.position = _FirstBackgroundPos + moveBackground;
			}
		}
	}
}
