//>>> _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.ID79ca9be5_ad6f_41f0_a4e5_32e9f5191d1e
{
    public class Class_BeatPulse : OperatorPart.Function, Framefield.Core.OperatorPartTraits.ITimeAccessor
    {
        //>>> _inputids
        private enum InputId
        {
            BPM = 0,
            BPMTimeOffset = 1,
            Ticks = 2,
            BeatsPerBar = 3,
            OutputRangeMax = 4,
            OutputRangeMin = 5,
            OverrideSyncedTime = 6
        }
        //<<< _inputids
        
        //>>> _outputids
        private enum OutputId
        {
            Beat = 0,
            SyncedTime = 1
        }
        //<<< _outputids
        
        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx) 
        {
            //>>> _params
            var BPM = inputs[(int)InputId.BPM].Eval(context).Value;
            var BPMTimeOffset = inputs[(int)InputId.BPMTimeOffset].Eval(context).Value;
            var Ticks = inputs[(int)InputId.Ticks].Eval(context).Text;
            var BeatsPerBar = inputs[(int)InputId.BeatsPerBar].Eval(context).Value;
            var OutputRangeMax = inputs[(int)InputId.OutputRangeMax].Eval(context).Value;
            var OutputRangeMin = inputs[(int)InputId.OutputRangeMin].Eval(context).Value;
            var OutputRange = new Vector2(OutputRangeMax, OutputRangeMin);
            var OverrideSyncedTime = inputs[(int)InputId.OverrideSyncedTime].Eval(context).Value;
            //<<< _params

            var steps = (float)Ticks.Length;
            if( steps <=0){
                Logger.Warn(this, "Ticks must be at least a characters long");
                return context;
            }
            
            //steps = 4;
            var time = context.GlobalTime - BPMTimeOffset;

            var x = 60 / BPM * BeatsPerBar ;
            
            var barTime = (time % x) / x;
            
            float maxValue = 0;
            foreach(var c in Ticks) {
                double v =0;
                Double.TryParse(""+c, out v);
                if( v > maxValue)
                    maxValue = (float)v;                
            }
            
            if(OverrideSyncedTime != 0) {
                barTime = OverrideSyncedTime * BeatsPerBar % 1;
            }
            
            
            var stepIndex = (int)Math.Floor( barTime * steps) ;
            if(stepIndex <0 )
                stepIndex = 0;
                
            double stepStrength;
            Double.TryParse( "" + Ticks[stepIndex], out stepStrength );
            var strength = (float)stepStrength / maxValue;

            float stepTime = barTime * steps - stepIndex;
            float stepBeat = (1-stepTime) * strength;
            
            float returnValue = 0;
            switch( outputIdx ) {
                case (int)OutputId.Beat:
                    returnValue = stepBeat * (OutputRangeMax - OutputRangeMin) + OutputRangeMin;
                    break;
                case (int)OutputId.SyncedTime:
                    returnValue = time/x;
                    break;
            }
            context.Value = returnValue;
            
            return context;
        }
    }
}

