using Earthblend.DynamicCompile;
using Earthblend.Nts.Common;
using Earthblend.Nts.Common.Members;
using Earthblend.Nts.Common.MeshGenerators;
using Earthblend.Tts.Common.Core.Extentions;
using Earthblend.Tts.Common.Core.Members;
using Earthblend.Tts.Common.Core.Services;
using Earthblend.Tts.Common.Core.Statics;
using HelixToolkit.Wpf;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Threading;
using VirtualCanvasTestCode.MeshGenerators;
using VirtualCanvasTestCode.Models;
using VirtualCanvasTestCode.Services;

namespace VirtualCanvasTestCode
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {

        private RangeViewModel _rangeVm = null;
        public RangeViewModel RangeVm { get { return _rangeVm; } set { _rangeVm = value; RaisePropertyChanged("RangeVm"); } }

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }



        public MainWindow()
        {
            InitializeComponent();

            this.Loaded += MainWindow_Loaded;
            try
            {
                this.DataContext = new EquationTester();

                var dc = this.DataContext as EquationTester;
                dc.MathChanged += Dc_MathChanged;

                FileInfo fileInfo = new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);
                var executingAssembly = fileInfo.DirectoryName + @"\Resources\Images\";
                fileInfo = null;

                FileService fileService = new FileService();
                String path = VirtualSystemUtil.ApplicationStorageFolder + @"ConfigurationModels\Configuration.xml";
                //if (!File.Exists(path))
                //{
                path = executingAssembly + "Configuration.xml";
                //}

                var data = fileService.LoadProjectFile<RangeViewModel>(path, XmlUtil.LoadSaveTypes);

                RangeVm = (RangeViewModel)data;
                fileService = null;
                RaisePropertyChanged("RangeVm");

                RangeVm.Initialize(dc);
                RangeVm.RenderRequest += RangeVm_RenderRequest;

                Render();

                var tabGroup = RangeVm.CanvasItems.Items.GroupBy(c => c.NodeId);

                foreach (var group in tabGroup)
                {
                    dc.SlateInfos.Add(new SlateInfo() { IsSelected = false, Id = group.Key, Name = dc.CanvasTabs[group.Key] });
                }

                if (dc.SlateInfos.Any()) dc.SlateInfos.FirstOrDefault().IsSelected = true;

                foreach (var canvasItem in RangeVm.CanvasItems.Items) canvasItem.IsVisible = false;
                foreach (var canvasItem in RangeVm.CanvasItems.Items.Where(c => c.NodeId == dc.CanvasTabs.FirstOrDefault().Key)) canvasItem.IsVisible = true;

                if (dc.RenderText) RangeVm.RenderText(dc); else dc.TextModel3DGroup.Children.Clear();
            }
            catch (Exception ex)
            {
                String msg = ex.Message;
            }
        }

        private void RangeVm_RenderRequest(object sender, EventArgs e)
        {
            Render();
        }

        private void Render()
        {
            Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() =>
            {
                var dc = this.DataContext as EquationTester;
                Model3DGroupRenderService service = new Model3DGroupRenderService();

                service.VirtualWorldDataItems = RangeVm.WorldItems.Items.ToObservableCollection();
                service.VirtualCanvasPluginDataItems = RangeVm.CanvasItems.Items.ToObservableCollection();
                service.TargetDefinitions = RangeVm.TargetItems.Items.ToObservableCollection();

                dc.MainModel3DGroup.Children.Clear();

                #region Populate Class Values

                new TestCodeViewModel().UpdateClassValues(service, dc);

                #endregion

                foreach (var target in service.TargetDefinitions)
                {
                    var canvasItem = service.VirtualCanvasPluginDataItems.Where(c =>
                       c.EquationId == target.EquationId
                    && c.SymbolType == Earthblend.Tts.Common.Core.Enumerations.MathSymbolType.EquationVariable
                    && c.Sequence == 1);

                    var answerCanvasItem = service.VirtualCanvasPluginDataItems.Where(c =>
                       c.EquationId == target.EquationId
                    && c.SymbolType == Earthblend.Tts.Common.Core.Enumerations.MathSymbolType.Answer);

                    if (canvasItem != null && canvasItem.FirstOrDefault() != null)
                    {
                        target.VirtualResult = dc.GetFieldValue(new SubscriptService().TranslateSubscript(canvasItem.FirstOrDefault().DisplayText), dc);
                        if (answerCanvasItem.Any())
                        {
                            if (target.VirtualResult != null)
                                answerCanvasItem.FirstOrDefault().DisplayText = target.VirtualResult.ToString();
                        }
                    }
                }

                #region Repopulate non target answers

                foreach (var item in RangeVm.CanvasItems.Items.Where(c => c.SymbolType == Earthblend.Tts.Common.Core.Enumerations.MathSymbolType.EquationVariable))
                {
                    var answerCheck = RangeVm.CanvasItems.Items.Where(c => c.EquationId == item.EquationId && c.SymbolType == Earthblend.Tts.Common.Core.Enumerations.MathSymbolType.Answer);
                    if (answerCheck.Any())
                    {
                        object fieldValue = dc.GetFieldValue(new SubscriptService().TranslateSubscript(item.DisplayText), dc);
                        if (fieldValue != null) answerCheck.FirstOrDefault().DisplayText = fieldValue.ToString();
                    }
                }

                #endregion

                dc.MainModel3DGroup.Children.Add(service.Render(Guid.Empty, service.VirtualWorldDataItems));
                if (dc.RenderText == true) RangeVm.RenderText(dc); else dc.TextModel3DGroup.Children.Clear();
            }));
        }


        private void Dc_MathChanged(object sender, MathChangedEventArgs e)
        {
            Render();
            Render();
        }

        //MainModel3DGroup

        public long GetPasVal(int row, int col)
        {
            int factOfRow = 1, i;
            for (i = 1; i <= (row - 1); i++)
                factOfRow *= i;
            int factOfRowMinusCol = 1;
            for (i = 1; i <= (row - 1) - (col - 1); i++)
                factOfRowMinusCol *= i;
            int factOfCol = 1;
            for (i = 1; i <= (col - 1); i++)
                factOfCol *= i;
            int fact = factOfRow / (factOfCol * factOfRowMinusCol);
            return fact;
        }

        GeometryModel3D geometryModel3D = new GeometryModel3D();
        public Images Img { get; set; } = new Images();
        public long LongValue { get; set; } = 0;
        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            //this.DataContext = this;
            //RegisterEvent();
            //SetTheory p = new SetTheory();
            //p.ExecuteLiterals();

            //var result = p.A();

            //int i = 0;
            //var result = GetPasVal(6, 2 );



            //Earthblend.DynamicCompile.Power_Tests pt = new Earthblend.DynamicCompile.Power_Tests();

            //Earthblend.DynamicCompile.Pallet pallet = new Earthblend.DynamicCompile.Pallet();
            //var answer = pallet.EvaluateEquationGap(null);

            //EquationTester equ = new EquationTester();
            //var answer = equ.EvaluateEquation3(null);
            //var x = new FractionReducer(0, 375, 1000);
            //equ = null;
            //this.Title = answer.ToString();
            //this.DataContext = equ;

            //CustomMeshGenerator customMeshGenerator = new CustomMeshGenerator();

            //ModelVisual3D modelVisual3D = new ModelVisual3D();
            //Model3DGroup model3dGroup = new Model3DGroup();
            //modelVisual3D.Content = model3dGroup;

            //MeshGeometry3D mesh = new MeshGeometry3D();
            //mesh.Positions = Vm.Geometry.Positions;
            //mesh.TriangleIndices = Vm.Geometry.TriangleIndices;
            //mesh.TextureCoordinates = Vm.Geometry.TextureCoordinates;
            //mesh.Normals = Vm.Geometry.Normals;

            //if(!HasTextureCoordinates(mesh.TextureCoordinates))
            //{
            //    geometryModel3D.Material = new DiffuseMaterial(new SolidColorBrush() { Color = Colors.SeaGreen });
            //}
            //else geometryModel3D.Material = new DiffuseMaterial(new ImageBrush(new BitmapImage(new Uri(@"C:\Users\Doug Hagerman\Pictures\2OIP.jpg"))) );
            //geometryModel3D.BackMaterial = new DiffuseMaterial(new SolidColorBrush() { Color = Colors.Red });
            //geometryModel3D.Geometry = Vm.Geometry; //mesh;
            //geometryModel3D.Transform = new TranslateTransform3D(0, 0, 0);
            //model3dGroup.Children.Add(new DirectionalLight());
            //model3dGroup.Children.Add(geometryModel3D);
            //HelixTestViewport.Children.Add(modelVisual3D);

            #region Add Text Left

            //RibbonTextMeshGenerator ribbonTextMeshGeneratorLeft = new RibbonTextMeshGenerator() { Text= "+ X Left" };

            //MeshGeometry3D meshTextLeft = new MeshGeometry3D();
            //meshTextLeft.Positions = ribbonTextMeshGeneratorLeft.Geometry.Positions;
            //meshTextLeft.TriangleIndices = ribbonTextMeshGeneratorLeft.Geometry.TriangleIndices;
            //meshTextLeft.TextureCoordinates = ribbonTextMeshGeneratorLeft.Geometry.TextureCoordinates;
            //meshTextLeft.Normals = ribbonTextMeshGeneratorLeft.Geometry.Normals;

            //GeometryModel3D geometryModel3DTextLeft = new GeometryModel3D();
            //geometryModel3DTextLeft.Geometry = meshTextLeft;
            //geometryModel3DTextLeft.Material = new DiffuseMaterial(new SolidColorBrush(Colors.White));
            //geometryModel3DTextLeft.BackMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.SeaGreen));
            //TranslateTransform3D translateTransform3DLeft = new TranslateTransform3D(-6,0,0);

            //Transform3DGroup transform3DGroupLeft = new Transform3DGroup();

            //RotateTransform3D rotateXLeft = new RotateTransform3D() { CenterX = -6, CenterY=0,CenterZ = 0, Rotation = new AxisAngleRotation3D() { Angle = 90, Axis = new Vector3D(1, 0, 0) } };
            //RotateTransform3D rotateYLeft = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 0, Axis = new Vector3D(0, 1, 0) } };
            //RotateTransform3D rotateZLeft = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 180, Axis = new Vector3D(0, 0, 1) } };

            //transform3DGroupLeft.Children.Add(translateTransform3DLeft);
            //transform3DGroupLeft.Children.Add(rotateXLeft);
            //transform3DGroupLeft.Children.Add(rotateYLeft);
            //transform3DGroupLeft.Children.Add(rotateZLeft);

            //geometryModel3DTextLeft.Transform = transform3DGroupLeft;


            #endregion

            #region Add Text Right

            //RibbonTextMeshGenerator ribbonTextMeshGeneratorRight = new RibbonTextMeshGenerator() { Text="Right X -" };

            //MeshGeometry3D meshTextRight = new MeshGeometry3D();
            //meshTextRight.Positions = ribbonTextMeshGeneratorRight.Geometry.Positions;
            //meshTextRight.TriangleIndices = ribbonTextMeshGeneratorRight.Geometry.TriangleIndices;
            //meshTextRight.TextureCoordinates = ribbonTextMeshGeneratorRight.Geometry.TextureCoordinates;
            //meshTextRight.Normals = ribbonTextMeshGeneratorRight.Geometry.Normals;

            //GeometryModel3D geometryModel3DTextRight = new GeometryModel3D();
            //geometryModel3DTextRight.Geometry = meshTextRight;
            //geometryModel3DTextRight.Material = new DiffuseMaterial(new SolidColorBrush(Colors.White));
            //geometryModel3DTextRight.BackMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.SeaGreen));
            //TranslateTransform3D translateTransform3DRight = new TranslateTransform3D(6, 0, 0);

            //Transform3DGroup transform3DGroupRight = new Transform3DGroup();

            //RotateTransform3D rotateXRight = new RotateTransform3D() { CenterX = 6, CenterY = 0, CenterZ = 0, Rotation = new AxisAngleRotation3D() { Angle = 90, Axis = new Vector3D(1, 0, 0) } };
            //RotateTransform3D rotateYRight = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 0, Axis = new Vector3D(0, 1, 0) } };
            //RotateTransform3D rotateZRight = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 180, Axis = new Vector3D(0, 0, 1) } };

            //transform3DGroupRight.Children.Add(translateTransform3DRight);
            //transform3DGroupRight.Children.Add(rotateXRight);
            //transform3DGroupRight.Children.Add(rotateYRight);
            //transform3DGroupRight.Children.Add(rotateZRight);

            //geometryModel3DTextRight.Transform = transform3DGroupRight;

            #endregion

            #region Add Text Top

            //RibbonTextMeshGenerator ribbonTextMeshGeneratorTop = new RibbonTextMeshGenerator() { Text = "Top + Z" };

            //MeshGeometry3D meshTextTop = new MeshGeometry3D();
            //meshTextTop.Positions = ribbonTextMeshGeneratorTop.Geometry.Positions;
            //meshTextTop.TriangleIndices = ribbonTextMeshGeneratorTop.Geometry.TriangleIndices;
            //meshTextTop.TextureCoordinates = ribbonTextMeshGeneratorTop.Geometry.TextureCoordinates;
            //meshTextTop.Normals = ribbonTextMeshGeneratorTop.Geometry.Normals;

            //GeometryModel3D geometryModel3DTextTop = new GeometryModel3D();
            //geometryModel3DTextTop.Geometry = meshTextTop;
            //geometryModel3DTextTop.Material = new DiffuseMaterial(new SolidColorBrush(Colors.White));
            //geometryModel3DTextTop.BackMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.SeaGreen));
            //TranslateTransform3D translateTransform3DTop = new TranslateTransform3D(0, 0, 6);

            //Transform3DGroup transform3DGroupTop = new Transform3DGroup();

            //RotateTransform3D rotateXTop = new RotateTransform3D() { CenterX = 0, CenterY = 0, CenterZ = 6, Rotation = new AxisAngleRotation3D() { Angle = 90, Axis = new Vector3D(1, 0, 0) } };
            //RotateTransform3D rotateYTop = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 0, Axis = new Vector3D(0, 1, 0) } };
            //RotateTransform3D rotateZTop = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 180, Axis = new Vector3D(0, 0, 1) } };

            //transform3DGroupTop.Children.Add(translateTransform3DTop);
            //transform3DGroupTop.Children.Add(rotateXTop);
            //transform3DGroupTop.Children.Add(rotateYTop);
            //transform3DGroupTop.Children.Add(rotateZTop);

            //geometryModel3DTextTop.Transform = transform3DGroupTop;

            #endregion

            #region Add Text Bottom

            //RibbonTextMeshGenerator ribbonTextMeshGeneratorBottom = new RibbonTextMeshGenerator() { Text = "Bottom - Z" };

            //MeshGeometry3D meshTextBottom = new MeshGeometry3D();
            //meshTextBottom.Positions = ribbonTextMeshGeneratorBottom.Geometry.Positions;
            //meshTextBottom.TriangleIndices = ribbonTextMeshGeneratorBottom.Geometry.TriangleIndices;
            //meshTextBottom.TextureCoordinates = ribbonTextMeshGeneratorBottom.Geometry.TextureCoordinates;
            //meshTextBottom.Normals = ribbonTextMeshGeneratorBottom.Geometry.Normals;

            //GeometryModel3D geometryModel3DTextBottom = new GeometryModel3D();
            //geometryModel3DTextBottom.Geometry = meshTextBottom;
            //geometryModel3DTextBottom.Material = new DiffuseMaterial(new SolidColorBrush(Colors.White));
            //geometryModel3DTextBottom.BackMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.SeaGreen));
            //TranslateTransform3D translateTransform3DBottom = new TranslateTransform3D(0, 0, -6);

            //Transform3DGroup transform3DGroupBottom = new Transform3DGroup();

            //RotateTransform3D rotateXBottom = new RotateTransform3D() { CenterX = 0, CenterY = 0, CenterZ = -6, Rotation = new AxisAngleRotation3D() { Angle = 90, Axis = new Vector3D(1, 0, 0) } };
            //RotateTransform3D rotateYBottom = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 0, Axis = new Vector3D(0, 1, 0) } };
            //RotateTransform3D rotateZBottom = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 180, Axis = new Vector3D(0, 0, 1) } };

            //transform3DGroupBottom.Children.Add(translateTransform3DBottom);
            //transform3DGroupBottom.Children.Add(rotateXBottom);
            //transform3DGroupBottom.Children.Add(rotateYBottom);
            //transform3DGroupBottom.Children.Add(rotateZBottom);

            //geometryModel3DTextBottom.Transform = transform3DGroupBottom;

            #endregion

            #region Add Text Front

            //RibbonTextMeshGenerator ribbonTextMeshGeneratorFront = new RibbonTextMeshGenerator() { Text = "Front + Y" };

            //MeshGeometry3D meshTextFront = new MeshGeometry3D();
            //meshTextFront.Positions = ribbonTextMeshGeneratorFront.Geometry.Positions;
            //meshTextFront.TriangleIndices = ribbonTextMeshGeneratorFront.Geometry.TriangleIndices;
            //meshTextFront.TextureCoordinates = ribbonTextMeshGeneratorFront.Geometry.TextureCoordinates;
            //meshTextFront.Normals = ribbonTextMeshGeneratorFront.Geometry.Normals;

            //GeometryModel3D geometryModel3DTextFront = new GeometryModel3D();
            //geometryModel3DTextFront.Geometry = meshTextFront;
            //geometryModel3DTextFront.Material = new DiffuseMaterial(new SolidColorBrush(Colors.White));
            //geometryModel3DTextFront.BackMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.SeaGreen));
            //TranslateTransform3D translateTransform3DFront = new TranslateTransform3D(0, -6, 0);

            //Transform3DGroup transform3DGroupFront = new Transform3DGroup();

            //RotateTransform3D rotateXFront = new RotateTransform3D() { CenterX = 0, CenterY = -6, CenterZ = 0, Rotation = new AxisAngleRotation3D() { Angle = 90, Axis = new Vector3D(1, 0, 0) } };
            //RotateTransform3D rotateYFront = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 0, Axis = new Vector3D(0, 1, 0) } };
            //RotateTransform3D rotateZFront = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 180, Axis = new Vector3D(0, 0, 1) } };

            //transform3DGroupFront.Children.Add(translateTransform3DFront);
            //transform3DGroupFront.Children.Add(rotateXFront);
            //transform3DGroupFront.Children.Add(rotateYFront);
            //transform3DGroupFront.Children.Add(rotateZFront);

            //geometryModel3DTextFront.Transform = transform3DGroupFront;

            #endregion

            #region Add Text Back

            //RibbonTextMeshGenerator ribbonTextMeshGeneratorBack = new RibbonTextMeshGenerator() { Text = "Back - Y" };

            //MeshGeometry3D meshTextBack = new MeshGeometry3D();
            //meshTextBack.Positions = ribbonTextMeshGeneratorBack.Geometry.Positions;
            //meshTextBack.TriangleIndices = ribbonTextMeshGeneratorBack.Geometry.TriangleIndices;
            //meshTextBack.TextureCoordinates = ribbonTextMeshGeneratorBack.Geometry.TextureCoordinates;
            //meshTextBack.Normals = ribbonTextMeshGeneratorBack.Geometry.Normals;

            //GeometryModel3D geometryModel3DTextBack = new GeometryModel3D();
            //geometryModel3DTextBack.Geometry = meshTextBack;
            //geometryModel3DTextBack.Material = new DiffuseMaterial(new SolidColorBrush(Colors.White));
            //geometryModel3DTextBack.BackMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.SeaGreen));
            //TranslateTransform3D translateTransform3DBack = new TranslateTransform3D(0, 6, 0);

            //Transform3DGroup transform3DGroupBack = new Transform3DGroup();

            //RotateTransform3D rotateXBack = new RotateTransform3D() { CenterX = 0, CenterY = 6, CenterZ = 0, Rotation = new AxisAngleRotation3D() { Angle = 90, Axis = new Vector3D(1, 0, 0) } };
            //RotateTransform3D rotateYBack = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 0, Axis = new Vector3D(0, 1, 0) } };
            //RotateTransform3D rotateZBack = new RotateTransform3D() { Rotation = new AxisAngleRotation3D() { Angle = 180, Axis = new Vector3D(0, 0, 1) } };

            //transform3DGroupBack.Children.Add(translateTransform3DBack);
            //transform3DGroupBack.Children.Add(rotateXBack);
            //transform3DGroupBack.Children.Add(rotateYBack);
            //transform3DGroupBack.Children.Add(rotateZBack);

            //geometryModel3DTextBack.Transform = transform3DGroupBack;

            #endregion

            //model3dGroup.Children.Add(geometryModel3DTextLeft);
            //model3dGroup.Children.Add(geometryModel3DTextRight);
            //model3dGroup.Children.Add(geometryModel3DTextTop);
            //model3dGroup.Children.Add(geometryModel3DTextBottom);
            //model3dGroup.Children.Add(geometryModel3DTextFront);
            //model3dGroup.Children.Add(geometryModel3DTextBack);

            //this.DataContext = Vm;
            //customMeshGenerator = null;

            SetInitialSecondCameraAngle();

        }

        private void SetInitialSecondCameraAngle()
        {
            if (RangeVm == null) return;
            if (RangeVm.Vp==null) return;
            if (RangeVm.Vp2 == null) return;

            var pc1 = RangeVm.Vp.Camera as PerspectiveCamera;

            var pc = new PerspectiveCamera()
            {
                FieldOfView = pc1.FieldOfView
                ,
                NearPlaneDistance = pc1.NearPlaneDistance
                ,
                FarPlaneDistance = pc1.FarPlaneDistance
                ,
                LookDirection = pc1.LookDirection
                ,
                Position = pc1.Position
                ,
                UpDirection = pc1.UpDirection
            };

            var axisAngleRotation = new AxisAngleRotation3D(new Vector3D(0, 0, 1), 90);
            var rt = new RotateTransform3D() { Rotation = axisAngleRotation };
            pc.Transform = rt;

            RangeVm.Vp2.Camera = pc;

            var camera1 = RangeVm.Vp.Camera as PerspectiveCamera;
            var camera2 = RangeVm.Vp2.Camera as PerspectiveCamera;

            camera1.Position = new Point3D(camera1.Position.X, camera1.Position.Y, camera1.Position.Z);
            camera2.Position = new Point3D(camera1.Position.X, camera1.Position.Y, camera1.Position.Z);

            camera1.FieldOfView += 30;
            camera2.FieldOfView += 30;
        }

        public Boolean HasTextureCoordinates(PointCollection textureCoordinates)
        {
            foreach(var point in textureCoordinates)
            {
                if (point.X > 0 || point.Y > 0) return true;
            }

            return false;
        }

        private void Window_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if(Keyboard.IsKeyDown(Key.LeftShift))
            if(e.Key == System.Windows.Input.Key.Oem5)
            {

            }
        }

        public BackgroundWorker _worker = new BackgroundWorker() { WorkerSupportsCancellation = true };

        private void Parallel_Click(object sender, RoutedEventArgs e)
        {
            RangeVm.MatchResults.Clear();

            _worker.DoWork += DoWork;
            _worker.ProgressChanged += ProgressChanged;
            _worker.WorkerReportsProgress = true;
            _worker.WorkerSupportsCancellation = true;

            _worker.RunWorkerCompleted += _worker_RunWorkerCompleted;
            _worker.RunWorkerAsync();
        }

        private void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                ProgressInfo progressInfo = (ProgressInfo)e.UserState;
                TotalProgress = progressInfo.RealProgress;

                this.Title = TotalProgress.ToString();
            });
        }

        private long _totalProgress = 0;
        public long TotalProgress { get { return _totalProgress; } set { _totalProgress = value; RaisePropertyChanged("TotalProgress"); } } 

        private void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

        }

        private void DoWork(object sender, DoWorkEventArgs e)
        {
            int progress = 0;

            Parallel.For(Convert.ToInt64(RangeVm.WStart), Convert.ToInt64(RangeVm.WEnd), w =>
            {
                {
                    Parallel.For(Convert.ToInt64(RangeVm.HStart), Convert.ToInt64(RangeVm.HEnd), h =>
                    {
                        Parallel.For(Convert.ToInt64(RangeVm.ZStart), Convert.ToInt64(RangeVm.ZEnd), z =>
                        {
                            Interlocked.Increment(ref progress); _worker.ReportProgress(progress, new ProgressInfo() { RealProgress = progress });
                            CheckResults(w, h, z);
                        });
                    });
                }
            });
        }

        private void CheckResults(Double w,Double h,Double z)
        {


            Application.Current.Dispatcher.Invoke(() =>
            {
                Model3DGroupRenderService service = new Model3DGroupRenderService();
                FileService fileService = new FileService();

                var xmlWorld = fileService.SaveToXml<WorldItemsExport>(RangeVm.WorldItems, XmlUtil.LoadSaveTypes);
                var xmlCanvas = fileService.SaveToXml<CanvasItemsExport>(RangeVm.CanvasItems, XmlUtil.LoadSaveTypes);
                var xmlTargets = fileService.SaveToXml<TargetItemsExport>(RangeVm.TargetItems, XmlUtil.LoadSaveTypes);

                service.VirtualWorldDataItems = fileService.LoadFromXml<WorldItemsExport>(xmlWorld, XmlUtil.LoadSaveTypes).Items.ToObservableCollection();
                service.VirtualCanvasPluginDataItems = fileService.LoadFromXml<CanvasItemsExport>(xmlCanvas, XmlUtil.LoadSaveTypes).Items.ToObservableCollection();
                service.TargetDefinitions = fileService.LoadFromXml<TargetItemsExport>(xmlTargets, XmlUtil.LoadSaveTypes).Items.ToObservableCollection();

                EquationTester equationTester = new EquationTester() { MathChange = false };
                
                //equationTester.WSub1 = w;
                //equationTester.HSub1 = h;
                //equationTester.ZSub1 = z;

                //Compile
                //Update Canvas
                //Update Virtual Result
                //Apply Target to 3D


                //foreach(var dataItem in service.VirtualWorldDataItems)
                //{                    
                //    var targetCheck = service.TargetDefinitions.Where(c => c.TargetId == dataItem.Id);
                //    if(targetCheck.Any())
                //    {
                //        foreach(var targetItem in targetCheck)
                //        {
                //            var canvasCheck = service.VirtualCanvasPluginDataItems.Where(c=>c.EquationId )
                //            //targetItem.VirtualResult = 
                //        }
                //    }
                //}

                //foreach (var canvasItem in service.VirtualCanvasPluginDataItems.Where(c=>new SubscriptService().TranslateSubscript(c.Class)=="WSub1"))
                //{ 
                    
                //}


                //Update Targets
                new TestCodeViewModel().UpdateClassValues(service, equationTester);

                //Set Class values like "A"

                //if (equationTester.ASub4 > 31.9D && equationTester.ASub4 < 32.1D)
                //{
                    //Model3DGroupRenderService service = new Model3DGroupRenderService();

                    //var xmlWorld = fileService.SaveToXml<WorldItemsExport>(WorldItems, XmlUtil.LoadSaveTypes);
                    //var xmlCanvas = fileService.SaveToXml<CanvasItemsExport>(CanvasItems, XmlUtil.LoadSaveTypes);
                    //var xmlTargets = fileService.SaveToXml<TargetItemsExport>(TargetItems, XmlUtil.LoadSaveTypes);

                    //service.VirtualWorldDataItems = fileService.LoadFromXml<WorldItemsExport>(xmlWorld, XmlUtil.LoadSaveTypes).Items.ToObservableCollection();
                    //service.VirtualCanvasPluginDataItems = fileService.LoadFromXml<CanvasItemsExport>(xmlCanvas, XmlUtil.LoadSaveTypes).Items.ToObservableCollection();
                    //service.TargetDefinitions = fileService.LoadFromXml<TargetItemsExport>(xmlTargets, XmlUtil.LoadSaveTypes).Items.ToObservableCollection();

                    //fileService = null;

                    #region Populate Class Values

                    //new TestCodeViewModel().UpdateClassValues(service, equationTester);

                    #endregion

                    foreach (var target in service.TargetDefinitions)
                    {
                        var canvasItem = service.VirtualCanvasPluginDataItems.Where(c =>
                           c.EquationId == target.EquationId
                        && c.SymbolType == Earthblend.Tts.Common.Core.Enumerations.MathSymbolType.EquationVariable
                        && c.Sequence == 1);

                        var answerCanvasItem = service.VirtualCanvasPluginDataItems.Where(c =>
                           c.EquationId == target.EquationId
                        && c.SymbolType == Earthblend.Tts.Common.Core.Enumerations.MathSymbolType.Answer);

                        if (canvasItem != null)
                        {
                            target.VirtualResult = equationTester.GetFieldValue(new SubscriptService().TranslateSubscript(canvasItem.FirstOrDefault().DisplayText), equationTester);

                            if (answerCanvasItem.Any())
                            {
                                answerCanvasItem.FirstOrDefault().DisplayText = target.VirtualResult.ToString();
                            }
                        }
                    }

                    #region Repopulate non target answers

                    foreach (var item in RangeVm.CanvasItems.Items.Where(c => c.SymbolType == Earthblend.Tts.Common.Core.Enumerations.MathSymbolType.EquationVariable))
                    {
                        var answerCheck = RangeVm.CanvasItems.Items.Where(c => c.EquationId == item.EquationId && c.SymbolType == Earthblend.Tts.Common.Core.Enumerations.MathSymbolType.Answer);
                        if (answerCheck.Any())
                        {
                            answerCheck.FirstOrDefault().DisplayText = equationTester.GetFieldValue(new SubscriptService().TranslateSubscript(item.DisplayText), equationTester).ToString();
                        }
                    }

                    #endregion

                    //equationTester.MainModel3DGroup.Children.Add(service.Render(Guid.Empty, service.VirtualWorldDataItems));

                    //MatchResult matchResult = new MatchResult() { W = equationTester.WSub1, H = equationTester.HSub1, D = equationTester.DSub1, Z = equationTester.ZSub1, CuFt = equationTester.ASub4 };
                    //matchResult.Model = equationTester.MainModel3DGroup;
                    //RangeVm.MatchResults.Add(matchResult);
                //}

                fileService = null;
                service = null;
            });
        }

        private void HelixTestViewport_Loaded(object sender, RoutedEventArgs e)
        {
            RangeVm.Vp = (HelixViewport3D)sender;
            SetInitialSecondCameraAngle();
        }

        private void HelixTestViewport_CameraChanged(object sender, RoutedEventArgs e)
        {
            var pc1 = ((HelixViewport3D)sender).Camera as PerspectiveCamera;

            var pc = new PerspectiveCamera() 
            { 
                FieldOfView = pc1.FieldOfView
                ,NearPlaneDistance = pc1.NearPlaneDistance
                ,FarPlaneDistance= pc1.FarPlaneDistance
                , LookDirection= pc1.LookDirection
                , Position= pc1.Position
                , UpDirection= pc1.UpDirection                
            };

            var axisAngleRotation = new AxisAngleRotation3D(new Vector3D(0,0,1),90);
            var rt = new RotateTransform3D() { Rotation = axisAngleRotation };
            pc.Transform = rt;

            HelixTestViewport2.Camera = pc;
        }

        private void HelixTestViewport2_Loaded(object sender, RoutedEventArgs e)
        {
            RangeVm.Vp2 = (HelixViewport3D)sender;
            SetInitialSecondCameraAngle();
        }
    }

    public class Images : CustomBindableBase
    {
        #region Private Variables

        private ImageDataItem _textureImage = new ImageDataItem() { ImagePath = @"Images\WorkflowSelector\", ImageName = "Slide.png" };

        #endregion

        #region Public Clr Properties

        public ImageDataItem TextureImage { get { return _textureImage; } set { SetProperty(ref _textureImage, value); } }

        #endregion
    }
}