//>>> _using
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.Windows;
//<<< _using
namespace Framefield.Core.ID9e3a5422_699e_4c1b_8627_32fd817c1ade
{

    public class Class_UpDownStepper : OperatorPart.Function, Framefield.Core.OperatorPartTraits.ITimeAccessor
    {
        //>>> _inputids
        private enum InputId
        {
            StartValue = 0,
            ResetTrigger = 1,
            UpTrigger = 2,
            DownTrigger = 3,
            StepSize = 4,
            Duration = 5
        }
        //<<< _inputids
        
        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx) {
            //>>> _params
            var StartValue = inputs[(int)InputId.StartValue].Eval(context).Value;
            var ResetTrigger = inputs[(int)InputId.ResetTrigger].Eval(context).Value;
            var UpTrigger = inputs[(int)InputId.UpTrigger].Eval(context).Value;
            var DownTrigger = inputs[(int)InputId.DownTrigger].Eval(context).Value;
            var StepSize = inputs[(int)InputId.StepSize].Eval(context).Value;
            var Duration = inputs[(int)InputId.Duration].Eval(context).Value;
            //<<< _params
            
            _duration = Duration;
            _time = context.GlobalTime;
            
            if(float.IsNaN(_targetValue)) {
                _targetValue = StartValue;
            }
            
            if( ResetTrigger > 0.5f) {
                _V = StartValue;
                _frozenValue = StartValue;
            }
            
            bool flankUpDetected = UpTrigger >= 0.5 && _oldUpTrigger <= 0.5;
            _oldUpTrigger = UpTrigger;
                        
            if( flankUpDetected ) {
                if(!_upActive) {
                    _lastValue = _V;
                    _V = _targetValue + StepSize;
                 }
                _upActive= true;
            }
            else {
                _upActive = false;
            }
            
            if( DownTrigger > 0.5f) {
                if(!_downActive) {
                    _lastValue = _V;
                    _V = _targetValue - StepSize;
                }
                _downActive = true;                
            }
            else {
                _downActive = false;
            }
            
            context.Value = _V;            
            return context;
        }
        
        float _V {
            get{
                if( _duration == 0 ){
                    return _targetValue;
                }    
                float d= Math.Min(1, Math.Max(0, _time - _startTime) / _duration) ;
                
                float d2= d * d * d * (d * (d * 6 - 15) + 10); //SmoothStep
                return _lastValue +(_targetValue - _lastValue) * d2;                
            }
            set {
                _lastValue= _V;
                _startTime = _time;
                _targetValue = value;
            }
        }
        
        private float _oldUpTrigger;
        private float _duration;
        private float _time =0;
        private float _frozenValue=0;
        private bool _upActive = false;
        private bool _downActive = false;
        private float _lastValue = 0f;
        private float _targetValue = float.NaN;
        private float _startTime = 0;
    }
}

