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

namespace Framefield.Core.ID94f2295a_ea64_4050_a9ea_b59bb959863c
{
    public class Class_RecordableCurve : Curve.Curve
    {
        //>>> _inputids
        private enum InputId
        {
            U = 0,
            V = 1,
            RecordEnabled = 2,
            EqualAngleThreshold = 3,
            ResetTrigger = 4
        }
        //<<< _inputids

        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx)
        {
            //>>> _params
            var U = inputs[(int)InputId.U].Eval(context).Value;
            var V = inputs[(int)InputId.V].Eval(context).Value;
            var RecordEnabled = (int) inputs[(int)InputId.RecordEnabled].Eval(context).Value;
            var EqualAngleThreshold = inputs[(int)InputId.EqualAngleThreshold].Eval(context).Value;
            var ResetTrigger = inputs[(int)InputId.ResetTrigger].Eval(context).Value;
            //<<< _params

            if( ResetTrigger > 0.5)
                State.Table.Clear();

            if (RecordEnabled > 0.5)
            {
            
                if(V == _lastV) {
                    context.Value = V;
                    return context;
                }
                _lastV = V;
            
                var state = State;
                var table = state.Table.ToList();
                //remove points 'right' from new U
                foreach (var e in table)
                {
                    if (e.Key > U)
                        state.Table.Remove(e.Key);
                }

                var lastPoint = state.Table.LastOrDefault(e => e.Key < U - Constants.Epsilon);
                var onePriorLastPoint = state.Table.LastOrDefault(e => e.Key < lastPoint.Key);
                double deviationAngle = 99999.9;
                if (lastPoint.Value != null && onePriorLastPoint.Value != null)
                {
                    var oldDir = new Vector2((float)(lastPoint.Key - onePriorLastPoint.Key), (float)(lastPoint.Value.Value - onePriorLastPoint.Value.Value));
                    oldDir.Normalize();
                    var newDir = new Vector2((float)(U - lastPoint.Key), (float)(V - lastPoint.Value.Value));
                    newDir.Normalize();
                    deviationAngle = Math.Acos((double)Vector2.Dot(oldDir, newDir))*180.0/Math.PI;
                }

                if (deviationAngle < EqualAngleThreshold)
                {
                    state.Table.Remove(lastPoint.Key);
                }
                
                state.Table[U] = new VDefinition() { Value = V };
                SplineInterpolator.UpdateTangents(state.Table.ToList());

                TriggerChangedEventIfEnabled();
                context.Value = V;
            }
            else
            {
                context.Value = (float)GetSampledValue(U);
            }
            return context;
        }
    private float _lastV=-1;
        
    }

    //only here so that an operatorpartstate can be found
    //and created
    public class CurveState : Curve.CurveState
    {
    }
} 
