//>>> _using
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.Windows;
//<<< _using
using SharpDX.DXGI;

namespace Framefield.Core.ID5a20234d_e781_4931_9cad_d7305b2aa667
{
    public class Class_MaskedGaussBlur : FXImageFunction
    {
        //>>> _inputids
        private enum InputId
        {
            Code = 0,
            Image = 1,
            Glow = 2,
            Offset = 3,
            Size = 4,
            NumberOfSamples = 5,
            Text = 6,
            Intensity = 7
        }
        //<<< _inputids

        protected override bool NeedsDepth { get { return false; } }

        protected override bool BuildRenderTarget(SharpDX.DXGI.Format imageBufferFormat)
        {
            var pass1ResourceChanged = ResourceManager.ValidateRenderTargetResource(ref _pass1RenderTargetResource, OperatorPart, D3DDevice.Device,
                                                                                    (int)_usedViewport.Width, (int)_usedViewport.Height);
            if (pass1ResourceChanged)
            {
                Utilities.DisposeObj(ref _pass1RenderTargetView);
                _pass1RenderTargetView = new RenderTargetView(D3DDevice.Device, _pass1RenderTargetResource.Texture);
            }

            return base.BuildRenderTarget(imageBufferFormat) || pass1ResourceChanged;
        }

        public override void Dispose()
        {
            ResourceManager.Dispose(_pass1RenderTargetResource);
            Utilities.DisposeObj(ref _pass1RenderTargetView);
            base.Dispose();
        }

        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx)
        {
            return PrepareAndEvalOnChange(context, () =>
            {
                //>>> _params
                var Code = inputs[(int)InputId.Code].Eval(context).Text;
                var Image = inputs[(int)InputId.Image].Eval(context).Image; // Needs to be checked for null!
                var Glow = inputs[(int)InputId.Glow].Eval(context).Value;
                var Offset = inputs[(int)InputId.Offset].Eval(context).Value;
                var Size = inputs[(int)InputId.Size].Eval(context).Value;
                var NumberOfSamples = inputs[(int)InputId.NumberOfSamples].Eval(context).Value;
                var Text = inputs[(int)InputId.Text].Eval(context).Text;
                var Intensity = inputs[(int)InputId.Intensity].Eval(context).Image; // Needs to be checked for null!
                //<<< _params
                
                if(Image == null) {
                    Logger.Info(this, "No image connected to blur");
                    return;
                }
                
                if(Intensity == null) {
                    Logger.Info(this, "No image to define blur-strength");
                    return;
                }

                var D3DDevice = context.D3DDevice;
                var cameraProjection = Matrix.OrthoLH(1, 1, -100, 100);
                var worldToCamera = Matrix.LookAtLH(new Vector3(0, 0, -5), new Vector3(0, 0, 0), new Vector3(0, 1, 0));

                _effect.GetVariableByName("widthToHeight").AsScalar().Set((float)_usedViewport.Width/_usedViewport.Height);
                _effect.GetVariableByName("Size").AsScalar().Set(Size);
                _effect.GetVariableByName("Glow").AsScalar().Set(Glow);
                _effect.GetVariableByName("Offset").AsScalar().Set(Offset);
                _effect.GetVariableByName("NumberOfSamples").AsScalar().Set(NumberOfSamples);

                //pass 1 (horizontal)
                D3DDevice.ImmediateContext.ClearRenderTargetView(_pass1RenderTargetView, new SharpDX.Color4(0, 0, 0, 1));

                var pass1SubContext = new OperatorPartContext(context);
                pass1SubContext.DepthStencilView = null;
                pass1SubContext.RenderTargetView = _pass1RenderTargetView;
                pass1SubContext.Effect = _effect;
                pass1SubContext.Renderer = _renderer;
                pass1SubContext.BlendState = OperatorPartContext.DefaultRenderer.DisabledBlendState;
                pass1SubContext.InputLayout = context.Renderer.ScreenQuadInputLayout;
                pass1SubContext.CameraProjection = cameraProjection;
                pass1SubContext.WorldToCamera = worldToCamera;
                pass1SubContext.ObjectTWorld = Matrix.Identity;
                
                using (var textureView = new ShaderResourceView(D3DDevice, Image))
                using (var intensityTextureView = new ShaderResourceView(D3DDevice, Intensity))
                {
                    pass1SubContext.Texture0 = textureView;
                    pass1SubContext.Effect.GetVariableByName("Intensity").AsShaderResource().SetResource(intensityTextureView);

                    //pass1SubContext.IntensityTexture = intensityTextureView;
                    pass1SubContext.Renderer.SetupEffect(pass1SubContext);

                    _effect.GetVariableByName("direction").AsVector().Set(new Vector2(1, 0));

                    pass1SubContext.Renderer.Render(pass1SubContext.Renderer._screenQuadMesh, pass1SubContext);
                }

                //pass 2 (vertical)
                D3DDevice.ImmediateContext.ClearRenderTargetView(_renderTargetView, new SharpDX.Color4(0, 0, 0, 1));

                var pass2SubContext = new OperatorPartContext(context);
                pass2SubContext.DepthStencilView = null;
                pass2SubContext.RenderTargetView = _renderTargetView;
                pass2SubContext.Effect = _effect;
                pass2SubContext.Renderer = _renderer;
                pass2SubContext.BlendState = OperatorPartContext.DefaultRenderer.DisabledBlendState;
                pass2SubContext.InputLayout = context.Renderer.ScreenQuadInputLayout;
                pass2SubContext.CameraProjection = cameraProjection;
                pass2SubContext.WorldToCamera = worldToCamera;
                pass2SubContext.ObjectTWorld = Matrix.Identity;
                
                using (var textureView = new ShaderResourceView(D3DDevice, _pass1RenderTargetResource.Texture))
                using (var intensityTextureView = new ShaderResourceView(D3DDevice, Intensity))
                {
                    pass2SubContext.Texture0 = textureView;
                    pass2SubContext.Effect.GetVariableByName("Intensity").AsShaderResource().SetResource(intensityTextureView);

                    pass2SubContext.Renderer.SetupEffect(pass2SubContext);

                    _effect.GetVariableByName("direction").AsVector().Set(new Vector2(0, 1));

                    pass2SubContext.Renderer.Render(pass2SubContext.Renderer._screenQuadMesh, pass2SubContext);
                }
            });
        }

        Resource _pass1RenderTargetResource = null;
        RenderTargetView _pass1RenderTargetView = null;
    }
}


