using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpDX;

namespace Framefield.Core.ID2a100d77_f3e2_4a3f_8496_dd6bba025a03
{
    public class Class_PerlinNoise1d : OperatorPart.Function
    {
        //>>> _inputids
        private enum InputId
        {
            Value = 0,
            Seed = 1,
            Period = 2,
            Octaves = 3,
            Zoom = 4,
            RangeMin = 5,
            RangeMax = 6
        }
        //<<< _inputids

        public float Noise(int x, int seed) {
            int n = x + seed*137;
            n = (n<<13) ^ n;
            return (float)( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0); 
        }
        
        public float Lerp(float a, float b, float t) {
            return a + t * (b - a);
        }
        
        public float Fade(float t) {
            return t * t * t * (t * (t * 6 - 15) + 10);
        }
        
        //public float Interpolate(float a, float b, float t) {
        //    float ft=t * 3.1415927f;
        //    float f= (float)(1.0 - Math.Cos(ft))* 0.5f;
        //    return (float)( a*(1.0f-f)+b*f);
        //}

        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx) {
        
            // >>> _params
            var Value = inputs[(int)InputId.Value].Eval(context).Value;
            var Seed = inputs[(int)InputId.Seed].Eval(context).Value;
            var Period = inputs[(int)InputId.Period].Eval(context).Value;
            var Octaves = inputs[(int)InputId.Octaves].Eval(context).Value;
            var Zoom = inputs[(int)InputId.Zoom].Eval(context).Value;
            var RangeMin = inputs[(int)InputId.RangeMin].Eval(context).Value;
            var RangeMax = inputs[(int)InputId.RangeMax].Eval(context).Value;
            var Range = new Vector2(RangeMin, RangeMax);
            // <<< _params
            
            
                int octaves = (int) Octaves;
                float noiseSum =0.0f;
                //float zoom= 2.0f;
                
                
                for(int a=0; a<octaves-1; a++) {
                    float frequency = (float)Math.Pow(2,a); 
                    float amplitude = (float)Math.Pow(Period ,a);

                    float v =  Value * frequency/Zoom  + Seed*12.468f ;
                                                   
                    noiseSum += Lerp( Noise( (int)v  , (int)Seed ),
                                      Noise( (int)v+1, (int)Seed ),
                                      Fade( v - (float)Math.Floor(v) )
                                )* amplitude;

                    //noiseSum += Interpolate( Noise( (int)v  , (int)Seed ) - 1,
                    //                         Noise( (int)v+1, (int)Seed ) - 1,
                    //                        v - (float)Math.Floor(v)
                    //            )* amplitude;

                }
                
               context.Value = (noiseSum+1f)*0.5f * (RangeMax-RangeMin) + RangeMin;

            return context;
        }
    }
}
