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


namespace ActionGame.UserInterface.Core
{
    public class Resolution : IResolution
    {
        private GraphicsDeviceManager graphicsDeviceManager = null;
        public Matrix InvertMatrix { get; private set; }
        public Matrix TransformationMatrix { get; private set; }
        public Int32 GameHeight { get; set; }
        public Int32 GameWidth { get; set; }
        public Int32 ActualHeight { get; set; }
        public Int32 ActualWidth { get; set; }


        public Resolution(GraphicsDeviceManager graphicsDeviceManager)
        {
            this.graphicsDeviceManager = graphicsDeviceManager;
        }


        public Viewport Viewport
        {
            get
            {
                return this.graphicsDeviceManager.GraphicsDevice.Viewport;
            }
        }


        public void Update()
        {
            ApplyResolutionSettings();

            ResetViewPort();

            CreateGameViewPort();

            RecreateScaleMatrix();
        }


        private void ApplyResolutionSettings()
        {
            if (graphicsDeviceManager.IsFullScreen == false)
            {
                graphicsDeviceManager.PreferredBackBufferWidth = ActualWidth;
                graphicsDeviceManager.PreferredBackBufferHeight = ActualHeight;
                graphicsDeviceManager.ApplyChanges();
            }
        }


        private void RecreateScaleMatrix()
        {
            if(this.graphicsDeviceManager == null)
            {
                return;
            }

            TransformationMatrix = Matrix.CreateScale(
                (float)graphicsDeviceManager.GraphicsDevice.Viewport.Width / GameWidth,
                (float)graphicsDeviceManager.GraphicsDevice.Viewport.Height / GameHeight,
                1f
            );

            InvertMatrix = Matrix.Invert(TransformationMatrix);
        }


        private void ResetViewPort()
        {
            Viewport vp = new Viewport()
            {
                X = 0,
                Y = 0,
                Width = this.ActualWidth,
                Height = this.ActualHeight
            };

            this.graphicsDeviceManager.GraphicsDevice.Viewport = vp;

            graphicsDeviceManager.GraphicsDevice.Clear(Color.Black);
        }


        private float GetVirtualAspectRatio()
        {
            return (float)GameWidth / (float)GameHeight;
        }


        private void CreateGameViewPort()
        {
            float targetAspectRatio = GetVirtualAspectRatio();
            int width = graphicsDeviceManager.PreferredBackBufferWidth;
            int height = (int)(width / targetAspectRatio + .5f);

            if (height > graphicsDeviceManager.PreferredBackBufferHeight)
            {
                height = graphicsDeviceManager.PreferredBackBufferHeight;
                
                width = (int)(height * targetAspectRatio + .5f);
            }

            Viewport viewport = new Viewport();

            viewport.X = (graphicsDeviceManager.PreferredBackBufferWidth / 2) - (width / 2);
            viewport.Y = (graphicsDeviceManager.PreferredBackBufferHeight / 2) - (height / 2);
            viewport.Width = width;
            viewport.Height = height;
            viewport.MinDepth = 0;
            viewport.MaxDepth = 1;

            graphicsDeviceManager.GraphicsDevice.Viewport = viewport;
        }


    }
}
