//>>> _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.ID244f16b8_d905_4598_8ffe_763ef64bd907
{
    public class Class_SetStateTime : OperatorPart.Function, Framefield.Core.OperatorPartTraits.IVariableAccessor, Framefield.Core.OperatorPartTraits.ITimeClip
    {
        //>>> _inputids
        private enum InputId
        {
            Input = 0,
            TimeVariableName = 1,
            AtEnd = 2,
            StartTime = 3,
            EndTime = 4,
            SceneWithoutWrapping = 5
        }
        //<<< _inputids

        public string VariableName
        {
            get
            {
                return OperatorPartUtilities.GetInputTextValue(OperatorPart.Connections[(int)InputId.TimeVariableName]);
            }
        }

        public double StartTime
        {
            get { return GetInputValue((int)InputId.StartTime); }
            set
            {
                _startTime = value;
                SetInputValue((int)InputId.StartTime, value);
                OperatorPart.EmitChangedEvent();
            }
        }

        public double EndTime
        {
            get { return GetInputValue((int)InputId.EndTime); }
            set
            {
                _endTime = value;
                SetInputValue((int)InputId.EndTime, value);
                OperatorPart.EmitChangedEvent();
            }
        }

        public double SourceStartTime
        {
            get { return _sourceStartTime; }
            set { _sourceStartTime = value; OperatorPart.EmitChangedEvent(); }
        }

        public double SourceEndTime
        {
            get { return _sourceEndTime; }
            set { _sourceEndTime = value; OperatorPart.EmitChangedEvent(); }
        }

        public int Layer
        {
            get { return _layer; }
            set { _layer = value; OperatorPart.EmitChangedEvent(); }
        }

        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx)
        {
            //>>> _params 
            var Input = inputs[(int)InputId.Input];
            var TimeVariableName = inputs[(int)InputId.TimeVariableName].Eval(context).Text;
            var AtEnd = (int) inputs[(int)InputId.AtEnd].Eval(context).Value;
            var StartTime = inputs[(int)InputId.StartTime].Eval(context).Value;
            var EndTime = inputs[(int)InputId.EndTime].Eval(context).Value;
            var SceneWithoutWrapping = inputs[(int)InputId.SceneWithoutWrapping];
            //<<< _params 

            var t = 0.0f;
            context.Variables.TryGetValue(TimeVariableName, out t);

            var oldTime = context.Time;
            _startTime = StartTime;
            _endTime = EndTime;

            switch (AtEnd)
            {
                case 0 : //continue
                    context.Time = t + (float)_startTime;
                    break;
                case 1 : //wrap
                    context.Time = t%(float)(_endTime - _startTime) + (float)_startTime;
                    break;
                case 2 : //stop
                    context.Time = (float)Utilities.Clamp(t + _startTime, _startTime, _endTime);
                    break;
            }

            _timeAccessorInvalidator.Clear();
            Input.TraverseWithFunctionUseSpecificBehavior(null, _timeAccessorInvalidator);
            Input.Eval(context);
            
            context.Time = t + (float)_startTime;            
            SceneWithoutWrapping.Eval(context);


            context.Time = oldTime;
            return context;
        }

        private void SetInputValue(int index, double val)
        {
            OperatorPart opPart = OperatorPart.Connections[index];
            if (opPart.Connections.Count == 0)
            {
                opPart.Func = Utilities.CreateValueFunction(new Float((float)val));
            }
        }
        
        private double GetInputValue(int index)
        {
            return OperatorPartUtilities.GetInputFloatValue(OperatorPart.Connections[index]);
        }

        double _startTime = 0;
        double _endTime = 10;
        double _sourceStartTime = 0;
        double _sourceEndTime = 10;
        int _layer = 0;
        OperatorPart.InvalidateTimeAccessors _timeAccessorInvalidator = new OperatorPart.InvalidateTimeAccessors();
    }
}


