using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace LunaLightXMG
{
    public class Camera2D
    {
        // Fields
        private readonly Viewport viewport;
        private float zoom;
        private float rotation;
        private Vector2 position;
        private Rectangle levelBounds;
        
        // Getters and setters
        public Vector2 Position
        {
            get => position;
            set => position = value;
        }
        public float Zoom
        {
            get => zoom;
            set => zoom = (int)Math.Floor(MathHelper.Clamp(value, 1f, 3f));
        }
        public float Rotation
        {
            get => rotation;
            set => rotation = value;
        }
        
        // constructor
        public Camera2D(int width, int height)
        {
            this.viewport = new Viewport(0, 0, width, height);
            levelBounds = new Rectangle(0, 0, 320, 180); // Default
            zoom = 1f;
            rotation = 0f;
            position = Vector2.Zero;
        }
        
        public Matrix GetViewMatrix()
        {
            return
                Matrix.CreateTranslation(new Vector3(-position, 0f)) *
                Matrix.CreateRotationZ(rotation) *
                Matrix.CreateScale(zoom, zoom, 1f) *
                Matrix.CreateTranslation(new Vector3(viewport.Width * 0.5f, viewport.Height * 0.5f, 0f));
        }

        public void SetLevelBounds(Rectangle bounds)
        {
            levelBounds = bounds;
        }

        public void Follow(Vector2 targetPostion)
        {
            // temp code
            Vector2 smoothPosition = Vector2.Lerp(position, targetPostion, 0.1f);
            position = smoothPosition;
            ClampToBounds();
        }

        private void ClampToBounds()
        {
            // Calculate the cam's half viewport size
            var halfViewportWidth = viewport.Width * 0.5f / zoom;
            var halfViewportHeight = viewport.Height * 0.5f / zoom;
            
            // Clamp cam to level bounds
            float minX = levelBounds.Left + halfViewportWidth;
            float maxX = levelBounds.Right - halfViewportWidth;
            float minY = levelBounds.Top + halfViewportHeight;
            float maxY = levelBounds.Bottom - halfViewportHeight;

            // Set cam position within level bounds
            position.X = MathHelper.Clamp(position.X, minX, maxX);
            position.Y = MathHelper.Clamp(position.Y, minY, maxY);
        }
    }
}