//>>> _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;
using SharpDX.D3DCompiler;
using SharpDX.Direct3D; 
using Framefield.Core.Rendering;
using System.Dynamic;
using Framefield.Core;

namespace Framefield.Core.ID17edb483_8ac4_4de6_af55_da4f0cd357be
{
    public class Class_ChromaticAbberation2 : FXImageFunction
    {
        //>>> _inputids
        private enum InputId
        {
            Code = 0,
            Image = 1,
            Strength = 2,
            Threshold = 3,
            RaySamples = 4,
            Size = 5,
            ColorR = 6,
            ColorG = 7,
            ColorB = 8,
            ColorA = 9,
            BlurSamples = 10,
            BlurSize = 11,
            CenterX = 12,
            CenterY = 13
        }
        //<<< _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 imageInput = inputs[(int)InputId.Image].Eval(context);

                var Strength = inputs[(int)InputId.Strength].Eval(context).Value;
                var Rays = inputs[(int)InputId.Threshold].Eval(context).Value;
                var RaySamples = inputs[(int)InputId.RaySamples].Eval(context).Value;
                var Size = inputs[(int)InputId.Size].Eval(context).Value;
                var ColorR = inputs[(int)InputId.ColorR].Eval(context).Value;
                var ColorG = inputs[(int)InputId.ColorG].Eval(context).Value;
                var ColorB = inputs[(int)InputId.ColorB].Eval(context).Value;
                var ColorA = inputs[(int)InputId.ColorA].Eval(context).Value;
                var Color = new Color4(ColorR, ColorG, ColorB, ColorA);                
                var BlurSamples = inputs[(int)InputId.BlurSamples].Eval(context).Value;
                var BlurSize = inputs[(int)InputId.BlurSize].Eval(context).Value;
                var CenterX = inputs[(int)InputId.CenterX].Eval(context).Value;
                var CenterY = inputs[(int)InputId.CenterY].Eval(context).Value;
                var Center = new Vector2(CenterX, CenterY);                
                //<<< __params
               
                var image = imageInput.Image;
                //var depthImage = imageInput.DepthImage;
                //if (image == null || depthImage == null)
                if (image == null)
                {
                    Logger.Error(this, "Image input missing");
                    return;
                }
    
                if (_renderer2 == null)
                {
                     _renderer2 = new BaseRenderer();
                }

                var D3DDevice = context.D3DDevice;


                var shaderDesc = new ShaderResourceViewDescription();
                shaderDesc.Format = Format.R32_Float;
                shaderDesc.Dimension = ShaderResourceViewDimension.Texture2D;
                shaderDesc.Texture2D.MipLevels = 1;


                //pass 1: original godrays
                //using (var depthTexture = new ShaderResourceView(context.D3DDevice, depthImage, shaderDesc))
                using (var ImageView = new ShaderResourceView(context.D3DDevice, image))
                {
                    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.InputLayout = context.Renderer.ScreenQuadInputLayout;
                    pass1SubContext.CameraProjection = Matrix.OrthoLH(1, 1, -100, 100);
                    pass1SubContext.WorldToCamera = Matrix.Identity;
                    pass1SubContext.ObjectTWorld = Matrix.Identity;
                    pass1SubContext.TextureMatrix = Matrix.Identity;

                    pass1SubContext.Renderer.SetupEffect(pass1SubContext);

                    _effect.GetVariableByName("RenderTargetSize").AsVector().Set(new Vector2(_usedViewport.Width, _usedViewport.Height));
                    _effect.GetVariableByName("Image").AsShaderResource().SetResource(ImageView);
                    _effect.GetVariableByName("Strength").AsScalar().Set(Strength);
                    _effect.GetVariableByName("Threshold").AsScalar().Set(Rays);
                    _effect.GetVariableByName("Size").AsScalar().Set(Size);
                    _effect.GetVariableByName("RaySamples").AsScalar().Set(RaySamples);
                    _effect.GetVariableByName("Color").AsVector().Set(Color);

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

                //pass 2 directional blur
                using (var textureView = new ShaderResourceView(D3DDevice, _pass1RenderTargetResource.Texture))
                {
                    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 = _renderer2;
                    pass2SubContext.InputLayout = context.Renderer.ScreenQuadInputLayout;
                    pass2SubContext.CameraProjection = Matrix.OrthoLH(1, 1, -100, 100);
                    pass2SubContext.WorldToCamera = Matrix.Identity;
                    pass2SubContext.ObjectTWorld = Matrix.Identity;
                    pass2SubContext.TextureMatrix = Matrix.Identity;
                    pass2SubContext.Texture0 = textureView;
                    pass2SubContext.Renderer.SetupEffect(pass2SubContext);

                    _effect.GetVariableByName("BlurSamples").AsScalar().Set(BlurSamples);
                    _effect.GetVariableByName("BlurSize").AsScalar().Set(BlurSize);
                    _effect.GetVariableByName("Center").AsVector().Set(Center);

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

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

