//>>> _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;

namespace Framefield.Core.IDa5a0962c_cad1_47a9_9d12_e9ce42f61da5
{
    public class Class_GodRays : FXImageFunction
    {
        //>>> _inputids
        private enum InputId
        {
            Code = 0,
            Image = 1,
            Camera = 2,
            Strength = 3,
            Decay = 4,
            NumberOfSamples = 5,
            CenterX = 6,
            CenterY = 7,
            CenterZ = 8,
            Size = 9,
            ColorR = 10,
            ColorG = 11,
            ColorB = 12,
            ColorA = 13
        }
        //<<< _inputids

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

        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx)
        {
            return PrepareAndEvalOnChange(context, () =>
            {
                //>>> __params
                var imageInput = inputs[(int)InputId.Image].Eval(context);
                var Strength = inputs[(int)InputId.Strength].Eval(context).Value;
                var Decay = inputs[(int)InputId.Decay].Eval(context).Value;
                var NumberOfSamples = inputs[(int)InputId.NumberOfSamples].Eval(context).Value;
                var Camera = inputs[(int)InputId.Camera].Eval(context).Dynamic;
                var CenterX = inputs[(int)InputId.CenterX].Eval(context).Value;
                var CenterY = inputs[(int)InputId.CenterY].Eval(context).Value;
                var CenterZ = inputs[(int)InputId.CenterZ].Eval(context).Value;
                var Center = new Vector3(CenterX, CenterY, CenterZ);                
                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);
                //<<< __params
 


                var image = imageInput.Image;
                var depthImage = imageInput.DepthImage;
                if (image == null || depthImage == null || Camera == null)
                {
                    Logger.Error(this,"{0}: conditions not fulfilled", OperatorPart.Parent);
                    return;
                }
                Framefield.Core.OperatorPartTraits.ICameraProvider camProvider = Camera.This as Framefield.Core.OperatorPartTraits.ICameraProvider;
                if (camProvider == null)
                {
                    Logger.Error(this,"{0}: camera not defined", OperatorPart.Parent);
                    return;
                }

                var viewToWorld = Matrix.Identity;
                var previousWorldToView = Matrix.Identity;

                var worldToCamera = camProvider.CalculateWorldToCamera(context);
                var cameraToView = camProvider.CalculateCameraToView(context);
                viewToWorld = Matrix.Invert(worldToCamera*cameraToView);

                using (new PropertyStasher<OperatorPartContext>(context, "Time")) {
                    context.Time -= 0.01f;
                    var previousWorldToCamera = camProvider.CalculateWorldToCamera(context);
                    var previousCameraToView = camProvider.CalculateCameraToView(context);
                    previousWorldToView = previousWorldToCamera*previousCameraToView;
                }

                ClearRenderTarget(context, new SharpDX.Color4(0, 0, 0, 1));

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

                using (var depthTexture = new ShaderResourceView(context.D3DDevice, depthImage, shaderDesc))
                //>>> __setup
                using (var ImageView = new ShaderResourceView(context.D3DDevice, image))
                {
                    _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("Decay").AsScalar().Set(Decay);
                    _effect.GetVariableByName("Size").AsScalar().Set(Size);
                    _effect.GetVariableByName("NumberOfSamples").AsScalar().Set(NumberOfSamples);
                    
                    _effect.GetVariableByName("Center").AsVector().Set(new Vector3(CenterX, CenterY, CenterZ));
                    _effect.GetVariableByName("Color").AsVector().Set(new Vector4(ColorR, ColorG, ColorB, ColorA));
                    _effect.GetVariableByName("viewToWorld").AsMatrix().SetMatrix(viewToWorld);
                    _effect.GetVariableByName("previousWorldToView").AsMatrix().SetMatrix(previousWorldToView);
                    _effect.GetVariableByName("txDepth").AsShaderResource().SetResource(depthTexture); 
    
                    Render(context);

                //>>> _cleanup
                }
            });
        }
    }
}

