//>>> _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 Buffer = SharpDX.Direct3D11.Buffer;

namespace Framefield.Core.IDc7ee4db3_b926_415e_8158_a215b63d3635
{
    public class Class_PerlinNoise : FXImageFunction
    {
        //>>> _inputids
        private enum InputId
        {
            Code = 0,
            Scale = 1,
            NumOctaves = 2,
            Seed = 3
        }
        //<<< _inputids

        int[] _permutationTable = new int[512];
        int _permutaionTableSize = 512 * 4 * 4; // 512 entries * intSize * 16byte alignment padding
        Buffer _permutationTableConstBuffer;

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

        private void CalcPermutationTable(int seed)
        {
            var random = new Random(seed);
            for (int i = 0; i < 256; ++i)
            {
                var value = random.Next(256);
                _permutationTable[i] = value;
                _permutationTable[i + 256] = value;
            }
        }

        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 Scale = inputs[(int)InputId.Scale].Eval(context).Value;
                var NumOctaves = inputs[(int)InputId.NumOctaves].Eval(context).Value;
                var Seed = inputs[(int)InputId.Seed].Eval(context).Value;
                //<<< _params

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

                CalcPermutationTable((int)Seed);

                using (var data = new SharpDX.DataStream(_permutaionTableSize, true, true))
                {
                    foreach (var permutationEnty in _permutationTable)
                    {
                        data.Write(permutationEnty);
                        data.Write(new Vector3(0, 0, 0)); // padding values
                    }
                    data.Position = 0;

                    if (_permutationTableConstBuffer == null)
                    {
                        var bufferDesc = new BufferDescription
                        {
                            Usage = ResourceUsage.Default,
                            SizeInBytes = _permutaionTableSize,
                            BindFlags = BindFlags.ConstantBuffer
                        };
                        _permutationTableConstBuffer = new Buffer(context.D3DDevice, data, bufferDesc);
                    }
                    else
                    {
                        context.D3DDevice.ImmediateContext.UpdateSubresource(new DataBox(data.DataPointer, 0, 0), _permutationTableConstBuffer, 0);
                    }
                }
                var constBuffer = _effect.GetConstantBufferByName("PermutationTable");
                if (constBuffer != null && constBuffer.IsValid)
                {
                    constBuffer.SetConstantBuffer(_permutationTableConstBuffer);
                }

                //>>> _setup
                {
                    _effect.GetVariableByName("RenderTargetSize").AsVector().Set(new Vector2(_usedViewport.Width, _usedViewport.Height));
                    _effect.GetVariableByName("Scale").AsScalar().Set(Scale);
                    _effect.GetVariableByName("NumOctaves").AsScalar().Set(NumOctaves);
                    _effect.GetVariableByName("Seed").AsScalar().Set(Seed);
                //<<< _setup

                    Render(context);

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

    }
}

