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

using System.Runtime.InteropServices;
using Framefield.Core.Rendering;
using SharpDX.DXGI;
using SharpDX.D3DCompiler;
using Buffer = SharpDX.Direct3D11.Buffer;

namespace Framefield.Core.ID841f3c85_54db_453d_984f_917412fb010e
{
    public class Class_SurfacePositionAsImage : FXSceneFunction
    {
        public Class_SurfacePositionAsImage()
        {
            _renderer = new BaseRenderer();
        }

        //>>> _inputids
        private enum InputId
        {
            Code = 0,
            Scene = 1,
            RefreshTrigger = 2
        }
        //<<< _inputids

        public override void Dispose()
        {
            Utilities.DisposeObj(ref _texture);
            Utilities.DisposeObj(ref _renderTargetView);
            Utilities.DisposeObj(ref _renderer);
            base.Dispose();
        }

        protected bool BuildRenderTarget(OperatorPartContext context)
        {
            if (_texture != null && _texture.Description.Width == (int) _usedViewport.Width && _texture.Description.Height == (int)_usedViewport.Height)
            {
                return false;
            }

            //_usedViewport = context.Viewport;

            Utilities.DisposeObj(ref _texture);
            var textureDesc = new Texture2DDescription
                                  {
                                      BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
                                      Format = Format.R32G32B32A32_Float,
                                      Width = (int) _usedViewport.Width,
                                      Height = (int) _usedViewport.Height,
                                      MipLevels = 1,
                                      SampleDescription = new SampleDescription(1, 0),
                                      Usage = ResourceUsage.Default,
                                      OptionFlags = ResourceOptionFlags.None,
                                      CpuAccessFlags = CpuAccessFlags.None,
                                      ArraySize = 1
                                  };
            _texture = new Texture2D(context.D3DDevice, textureDesc);

            Utilities.DisposeObj(ref _renderTargetView);
            _renderTargetView = new RenderTargetView(D3DDevice.Device, _texture);

            return true;
        }

        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx) 
        {
            //>>> __params
            var Code = inputs[(int)InputId.Code].Eval(context).Text;
            var Scene = inputs[(int)InputId.Scene];
            var RefreshTrigger = inputs[(int)InputId.RefreshTrigger].Eval(context).Value;
            //<<< __params
            
            if (_effect == null)
            {
                Compile(0);
            }

            BuildRenderTarget(context);
            
            if (RefreshTrigger != _oldRefresh && RefreshTrigger > 0.5) 
            {
                Changed= true;
            }
            _oldRefresh = RefreshTrigger;
            
            //if (Changed)
            {
                context.D3DDevice.ImmediateContext.ClearRenderTargetView(_renderTargetView, new Color4(0, 0, 0, 0));
    
                _effect.GetVariableByName("RenderTargetSize").AsVector().Set(new Vector2(_usedViewport.Width, _usedViewport.Height));
    
                ShaderResourceView imageView = null;
    
                var subContext = new OperatorPartContext(context)
                                        {
                                            DepthStencilView = null,
                                            RenderTargetView = _renderTargetView,
                                            Effect = _effect,
                                            Renderer = _renderer,
                                            Viewport = _usedViewport,
                                            InputLayout = context.Renderer.SceneDefaultInputLayout,
                                            CameraProjection = Matrix.OrthoLH(1, 1, -100, 100),
    //                                        WorldToCamera = Matrix.LookAtLH(new Vector3(0, 0, -5), new Vector3(0, 0, 0), new Vector3(0, 1, 0)),
                                            WorldToCamera = Matrix.Identity,
                                            ObjectTWorld = Matrix.Identity,
                                            TextureMatrix = Matrix.Identity
                                        };
                //Logger.Info(this,"used viewport {0}/{1}", _usedViewport.Width, _usedViewport.Height);
                Scene.Eval(subContext);
    
                Utilities.DisposeObj(ref imageView);
                Changed = false;
            }
            
            context.Image = _texture;

            return context;
        }

        private Texture2D _texture;
        private RenderTargetView _renderTargetView;
        private Viewport _usedViewport = new Viewport(0, 0, 2048, 2048);
        private BaseRenderer _renderer;
        private bool _firstEval = true;
        private float _oldRefresh;
    }
}

