//>>> _using
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.Windows;
//<<< _using
using Framefield.Core.OperatorPartTraits;
using Framefield.Core.Rendering;
using Buffer = SharpDX.Direct3D11.Buffer;
using SharpDX.Direct3D;

namespace Framefield.Core.ID4115337d_0013_490b_94e4_52d0ad033d47
{
    public class Class_AddSpikes : FXSourceCodeFunction, IFXSceneSourceCode
    {
        //>>> _inputids
        private enum InputId
        {
            Code = 0,
            Size = 1,
            Mesh = 2,
            Facetize = 3,
            OffsetX = 4,
            OffsetY = 5,
            OffsetZ = 6
        }
        //<<< _inputids

        public Class_AddSpikes()
        {
        }

        public override void Dispose() 
        {
            Utilities.DisposeObj(ref _mesh);
            base.Dispose();
        }

        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx)
        {
            try
            {
                UpdateMesh(context, inputs);
                context.Mesh = _mesh;
            }
            catch (Exception exception)
            {
                Logger.Error(this, "Load Effect error: {0}", exception.Message);
            }

            return context;
        }

        bool _firstEval = true;
        private void UpdateMesh(OperatorPartContext context, List<OperatorPart> inputs)
        {
            if (_firstEval)
            {
                for (int i = 0; i < NumCodes(); ++i)
                    Compile(i);
                _firstEval = false;
                Changed = true;
            }

            if (!Changed && _mesh.Vertices != null)
                return;

            //>>> _params
            var Code = inputs[(int)InputId.Code].Eval(context).Text;
            var Size = inputs[(int)InputId.Size].Eval(context).Value;
            var Mesh = inputs[(int)InputId.Mesh].Eval(context).Mesh;
            var Facetize = inputs[(int)InputId.Facetize].Eval(context).Value;
            var OffsetX = inputs[(int)InputId.OffsetX].Eval(context).Value;
            var OffsetY = inputs[(int)InputId.OffsetY].Eval(context).Value;
            var OffsetZ = inputs[(int)InputId.OffsetZ].Eval(context).Value;
            var Offset = new Vector3(OffsetX, OffsetY, OffsetZ);
            //<<< _params

            
            if (Mesh == null)
                return;

            _mesh.AttributesSize = Mesh.AttributesSize;
            _mesh.NumTriangles = Mesh.NumTriangles * 3;
            _mesh.InputElements = Mesh.InputElements;
            if (_mesh.Vertices == null || _mesh.Vertices.Description.SizeInBytes != Mesh.Vertices.Description.SizeInBytes)
            {
                if (_mesh.Vertices != null)
                    _mesh.Vertices.Dispose();

                _mesh.Vertices = new Buffer(D3DDevice.Device, new BufferDescription()
                                                                    {
                                                                        BindFlags = BindFlags.StreamOutput | BindFlags.VertexBuffer,
                                                                        CpuAccessFlags = CpuAccessFlags.None,
                                                                        OptionFlags = ResourceOptionFlags.None,
                                                                        SizeInBytes = _mesh.NumTriangles*Mesh.AttributesSize*3,
                                                                        Usage = ResourceUsage.Default
                                                                    });
            }
            

            
            _effect.GetVariableByName("Facetize").AsScalar().Set(Facetize);
            _effect.GetVariableByName("Offset").AsVector().Set(new Vector3(OffsetX, OffsetY, OffsetZ));
            _effect.GetVariableByName("Size").AsScalar().Set(Size);

            context.D3DDevice.ImmediateContext.StreamOutput.SetTargets(new [] { new StreamOutputBufferBinding(_mesh.Vertices, 0) });
            context.D3DDevice.ImmediateContext.OutputMerger.DepthStencilState = new DepthStencilState(context.D3DDevice,
                                                                                                        new DepthStencilStateDescription()
                                                                                                            {
                                                                                                                IsDepthEnabled = false,
                                                                                                                IsStencilEnabled = false
                                                                                                            });
            context.D3DDevice.ImmediateContext.InputAssembler.InputLayout = context.InputLayout;
            context.D3DDevice.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            context.D3DDevice.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(Mesh.Vertices, Mesh.AttributesSize, 0));
            var technique = _effect.GetTechniqueByIndex(0);
            technique.GetPassByIndex(0).Apply(context.D3DDevice.ImmediateContext);
            context.D3DDevice.ImmediateContext.Draw(_mesh.NumTriangles*3, 0);
            context.D3DDevice.ImmediateContext.StreamOutput.SetTargets(new [] { new StreamOutputBufferBinding(null, 0) });

            Changed = false;
        }

        private Mesh _mesh = new Mesh();
    }
}


