using System;
using ComponentFramework;
using ComponentFramework.Modules;
using MTV3D65;

namespace FullScreenShaders.Services
{
    class Rendering : Service, IRendering
    {
        TVViewport viewport;
        int lastDownscaleFactor;

        public event Action ViewportSizeChanged;

        public Rendering(ICore core) : base(core) { }

        public override void Initialize()
        {
            RebuildSurfaces();

            viewport = Core.Engine.GetViewport();
        }

        public override void Update(TimeSpan elapsedTime)
        {
            var newViewportSize = new TV_2DVECTOR(viewport.GetWidth(), viewport.GetHeight());

            if (newViewportSize.x != ViewportSize.x || newViewportSize.y != ViewportSize.y)
                OnViewportSizeChanged(newViewportSize);

            if(lastDownscaleFactor != SampleState.DownscaleFactor)
            {
                lastDownscaleFactor = SampleState.DownscaleFactor;
                RebuildSurfaces();

                OnViewportSizeChanged(newViewportSize);
            }
        }

        void RebuildSurfaces()
        {
            if (PostSurface != null)
                PostSurface.Destroy();
            PostSurface = Scene.CreateRenderSurfaceEx(-1, -1, CONST_TV_RENDERSURFACEFORMAT.TV_TEXTUREFORMAT_X8R8G8B8, 
                false, true, 1.0f / SampleState.DownscaleFactor);

            if (TempSurface != null)
            {
                TempSurface.Destroy();
                TempSurface = null;
            }
            if (SampleState.Downscaling)
                TempSurface = Scene.CreateRenderSurfaceEx(-1, -1, CONST_TV_RENDERSURFACEFORMAT.TV_TEXTUREFORMAT_X8R8G8B8, 
                    false, true, 1.0f / SampleState.DownscaleFactor);
        }

        void OnViewportSizeChanged(TV_2DVECTOR newSize)
        {
            ViewportSize = newSize / SampleState.DownscaleFactor;
            TexelSize = new TV_2DVECTOR(1 / ViewportSize.x, 1 / ViewportSize.y);

            if (ViewportSizeChanged != null)
                ViewportSizeChanged();            
        }

        public TV_2DVECTOR ViewportSize { get; private set; }
        public TV_2DVECTOR TexelSize { get; private set; }

        public TVRenderSurface PostSurface { get; private set; }
        public TVRenderSurface TempSurface { get; private set; }

        [ServiceDependency]
        public ISampleState SampleState { private get; set; }
    }

    interface IRendering : IService
    {
        event Action ViewportSizeChanged;

        TV_2DVECTOR ViewportSize { get; }
        TV_2DVECTOR TexelSize { get; }

        TVRenderSurface PostSurface { get; }
        TVRenderSurface TempSurface { get; }
    }
}
