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

namespace LunaLightXMG
{
    public class RenderHandler
    {
        // fields 
        private readonly GraphicsDevice graphicsDevice;
        private readonly SpriteBatch spriteBatch;
        private readonly RenderTarget2D renderTarget;
        private Rectangle renderDestination;
        
        private readonly float retroWidth;
        private readonly float retroHeight;
        private float zoomLevel = 1.0f;
        private float zoomTarget = 1.0f;
        private readonly float zoomMin = 0.50f;
        private readonly float zoomNorm = 1.0f;
        private readonly float zoomMax = 1.50f;
        private readonly float zoomSpeed = 0.1f;
        public float ZoomLevel {get => zoomLevel;}
        
        // constructor
        public RenderHandler(GraphicsDevice graphicsDevice, SpriteBatch spriteBatch, int retroWidth, int retroHeight)
        {
            this.graphicsDevice = graphicsDevice;
            this.spriteBatch = spriteBatch;
            this.retroWidth = retroWidth;
            this.retroHeight = retroHeight;
            
            renderTarget = new RenderTarget2D(graphicsDevice, retroWidth, retroHeight);

            CalculateRenderDestination();
        }
        
        public void ZoomIn()
        {
            zoomTarget = zoomMin;
        }
        
        public void ZoomNormalize()
        {
            zoomTarget = zoomNorm;
        }

        public void ZoomOut()
        {
            zoomTarget = zoomMax;
        }
        
        public void UpdateZoom()
        {
            // interpolate to target
            zoomLevel = MathHelper.Lerp(zoomLevel, zoomTarget, zoomSpeed);
            // snap to target when we're close enough 
            if (Math.Abs(zoomLevel - zoomTarget) < 0.001f) 
            {
                zoomLevel = zoomTarget;
            }
            // stay in bounds (just in case)
            zoomLevel = MathHelper.Clamp(zoomLevel, zoomMin, zoomMax);
            // calc new zoomed render destination
            CalculateRenderDestination();
        }
        
        public void CalculateRenderDestination()
        {
            Point screenSize = graphicsDevice.Viewport.Bounds.Size;
            // Calculate the integer scale factor
            float scaleX = screenSize.X / (retroWidth * zoomLevel);
            float scaleY = screenSize.Y / (retroHeight * zoomLevel);
            float scale = Math.Min(scaleX, scaleY);
            
            // Set renderDestination 
            renderDestination.Width = (int)(retroWidth * scale);
            renderDestination.Height = (int)(retroHeight * scale);
            renderDestination.X = (screenSize.X - renderDestination.Width) / 2;
            renderDestination.Y = (screenSize.Y - renderDestination.Height) / 2;
        }
    
        public void BeginRenderTarget(Matrix cameraMatrix)
        {
            graphicsDevice.SetRenderTarget(renderTarget);
            graphicsDevice.Clear(Color.Black);

            spriteBatch.Begin(transformMatrix: cameraMatrix, samplerState: SamplerState.PointClamp);
        }
        
        public void EndRenderTarget()
        {
            spriteBatch.End();
            graphicsDevice.SetRenderTarget(null);
        }

        public void DrawRenderTarget()
        {
            spriteBatch.Begin(samplerState: SamplerState.PointClamp);
            spriteBatch.Draw(renderTarget, renderDestination, Color.White);
            spriteBatch.End();
        }

        public void DrawRenderTarget(Player player, SpriteFont debugFont, Camera2D camera2D)
        {
            spriteBatch.Begin(samplerState: SamplerState.PointClamp);
            spriteBatch.Draw(renderTarget, renderDestination, Color.White);
            DebugInfo(player, debugFont, camera2D);
            spriteBatch.End();
        }

        public void DebugInfo(Player player, SpriteFont debugFont, Camera2D camera2D)
        {
            // Draw debug messages
            spriteBatch.DrawString(debugFont, $"VSP: {player.vsp}", new Vector2(10, 10), Color.White);
            spriteBatch.DrawString(debugFont, $"Grounded: {player.grounded}", new Vector2(10, 30), Color.White);
            spriteBatch.DrawString(debugFont, $"Walled: {player.walled}", new Vector2(10, 50), Color.White);
            spriteBatch.DrawString(debugFont, $"Position: {player.position}", new Vector2(10, 70), Color.White);
            spriteBatch.DrawString(debugFont, $"Camera Position: {camera2D.Position}", new Vector2(10, 90), Color.White);
            spriteBatch.DrawString(debugFont, $"Camera Rotation: {camera2D.Rotation}", new Vector2(10, 110), Color.White);
            spriteBatch.DrawString(debugFont, $"Render Target Zoom: {ZoomLevel}", new Vector2(10, 130), Color.White);

            spriteBatch.DrawString(debugFont, $"Camera Rotation Control - Rotate left: K, Rotate right: L", new Vector2(10, 190), Color.White);
            spriteBatch.DrawString(debugFont, $"Render Target Zoom Control - Zoom in: U, Zoom normal: I, Zoom out: O", new Vector2(10, 210), Color.White);
            spriteBatch.DrawString(debugFont, $"Press P to test screen shake.", new Vector2(10, 230), Color.White);
            spriteBatch.DrawString(debugFont, $"Press M to toggle game music.", new Vector2(10, 250), Color.White);
            spriteBatch.DrawString(debugFont, $"Press R to reset level.", new Vector2(10, 270), Color.White);
        }

    }
}