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

namespace Framefield.Core.ID8f942212_2dab_4d98_8172_fb1f142bc701
{
    public class Class_ReduceResolution : OperatorPart.Function
    {
        //>>> _inputids
        private enum InputId
        {
            Image = 0,
            Divide = 1
        }
        //<<< _inputids

        public Class_ReduceResolution() {
            try {
                using (var bytecode = ShaderBytecode.CompileFromFile("assets-common/fx/Resize.fx", "fx_5_0", ShaderFlags.None, EffectFlags.None, null, null))
                    _effect = new Effect(D3DDevice.Device, bytecode);
            }
            catch (Exception) {
                Logger.Debug(this,"error loading effect");
            }
        }

        private bool BuildRenderTarget() {
            var resourceChanged = ResourceManager.ValidateRenderTargetResource(ref _renderTargetResource, OperatorPart, D3DDevice.Device,
                                                                               (int)_usedViewport.Width, (int)_usedViewport.Height);
            if (resourceChanged) {
                Utilities.DisposeObj(ref _renderTargetView);
                _renderTargetView = new RenderTargetView(D3DDevice.Device, _renderTargetResource.Texture);
            }
            return resourceChanged;
        }

        public override void Dispose() {
            ResourceManager.Dispose(_renderTargetResource);
            Utilities.DisposeObj(ref _renderTargetView);
            Utilities.DisposeObj(ref _effect);
        }

        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx) {
            //>>> _params
            var Image = inputs[(int)InputId.Image].Eval(context).Image; if (Image == null) return context;
            var Divide = inputs[(int)InputId.Divide].Eval(context).Value;
            //<<< _params

            int width = (int)(context.Viewport.Width/Divide);
            int height = (int)(context.Viewport.Height/Divide);
            if (_usedViewport.Width != width || _usedViewport.Height != height) {
                _usedViewport = context.Viewport;
                _usedViewport.Width = width;
                _usedViewport.Height = height;
                Changed = true;
            }

            if (BuildRenderTarget())
                Changed = true;

            if (Changed) {
                var D3DDevice = context.D3DDevice;
                var subContext = new OperatorPartContext(context);
                subContext.Viewport = _usedViewport;
                subContext.DepthStencilView = null;
                subContext.RenderTargetView = _renderTargetView;

                try {
                    subContext.Effect = _effect;
                    subContext.InputLayout = context.Renderer.ScreenQuadInputLayout;
                    subContext.BlendState = OperatorPartContext.DefaultRenderer.DisabledBlendState;
                    var proj = Matrix.OrthoLH(1, 1, -100, 100);
                    subContext.CameraProjection = proj;
                    using (var textureView = new ShaderResourceView(D3DDevice, Image)) {
                        subContext.Texture0 = textureView;
                        subContext.Renderer.SetupEffect(subContext);
                        subContext.Renderer.Render(subContext.Renderer._screenQuadMesh, subContext);
                    }
                }
                catch (Exception exception) {
                    Logger.Error(this,"Load Effect error: {0}", exception.Message);
                }

                Changed = false;
            }

            context.Image = _renderTargetResource.Texture;
            return context;
        }

        Resource _renderTargetResource = null;
        RenderTargetView _renderTargetView = null;
        Effect _effect;

        Viewport _usedViewport = new Viewport(0, 0, 512, 512);
    }
}

