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

namespace Framefield.Core.IDa9360001_b86f_4734_9864_451830e2085e
{
    public class Class_TestsEvaluator : OperatorPart.Function, ITestEvaluator
    {
        //>>> _inputids
        private enum InputId
        {
            Inputs = 0,
            RunTrigger = 1,
            RebuildReferenceTrigger = 2,
            Filter = 3
        }
        //<<< _inputids

        public bool GetStartTestsEnabled(OperatorPartContext context)
        {
            var invalidator = new OperatorPart.InvalidateTimeAccessors();
            OperatorPart.Connections[(int)InputId.RunTrigger].TraverseWithFunction(null, invalidator);
            return OperatorPart.Connections[(int)InputId.RunTrigger].Eval(context).Value > 0.5;
        }

        public bool GetRebuildReferenceEnabled(OperatorPartContext context)
        {
            var invalidator = new OperatorPart.InvalidateTimeAccessors();
            OperatorPart.Connections[(int)InputId.RebuildReferenceTrigger].TraverseWithFunction(null, invalidator);
            return OperatorPart.Connections[(int)InputId.RebuildReferenceTrigger].Eval(context).Value > 0.5;
        }

        public string GetFilter(OperatorPartContext context)
        {
            var invalidator = new OperatorPart.InvalidateTimeAccessors();
            OperatorPart.Connections[(int)InputId.Filter].TraverseWithFunction(null, invalidator);
            return OperatorPart.Connections[(int)InputId.Filter].Eval(context).Text;
        }


        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx)
        {             
            Object evaluator = null;
            if (!context.Objects.TryGetValue(OperatorPartContext.TESTS_EVALUATOR_ID, out evaluator))
            {
                evaluator = this;

                //make input subtree invalid to ensure a full update
                foreach (var input in inputs[(int)InputId.Inputs].Connections)
                {
                    var testerCollector = new OperatorPart.CollectOpPartFunctionsOfType<TesterFunction>();
                    input.TraverseWithFunction(testerCollector, null);
                    foreach (var tester in testerCollector.CollectedOpPartFunctions)
                        tester.OperatorPart.EmitChangedEvent();
                }
            }

            string accumulatedInputResults = "";
            foreach (var input in inputs[(int)InputId.Inputs].Connections)
            {
                //during evaluation the object variables could be cleared. so we need to
                //set this before each evaluation
                context.Objects[OperatorPartContext.TESTS_EVALUATOR_ID] = evaluator;

                accumulatedInputResults += input.Eval(context).Text;
            }

            if (String.IsNullOrEmpty(accumulatedInputResults))
            {
                context.Text = "";
                return context;
            }
            
            String intendedInput = "";
            foreach (var line in accumulatedInputResults.Split('\n'))
            {
                if (!String.IsNullOrEmpty(line))
                    intendedInput += String.Format("    {0}\n", line);
            }
            
            String suiteResult = "";
            if (accumulatedInputResults.Contains("FAILED"))
                suiteResult = "FAILED";
            else if (accumulatedInputResults.Contains("reference updated"))
                suiteResult = "reference updated";
            else if (accumulatedInputResults.Contains("passed"))
                suiteResult = "passed";
            
            context.Text = String.Format("{0} : {1}\n{2}", OperatorPart.Parent.Parent.ToString(), suiteResult, intendedInput);
            _lastResult = context.Text;
            return context;
        }
        
        String _lastResult = "";
    }
}

