using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using System.Windows.Media.Media3D;
using Earthblend.Nts.Common;
using System.Text;

using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Earthblend.DynamicCompile;
using ConsoleTests;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Earthblend.Tts.Common.Core.CustomEventArgs;
using Earthblend.Nts.Common.MeshGenerators;

using Earthblend.Tts.Common.Core.Enumerations;

namespace ConsoleTests {}

namespace Earthblend.Nts.Common.MeshGenerators {}

namespace Earthblend.DynamicCompile
{
     public interface IMessage
     {
             List<String> Messages { get; set; }
     }

public class MathChangedEventArgs : EventArgs
{
public MathChangedEventArgs(Object obj)
{
     MathInfo = obj;
}
     public Object MathInfo { get; set; }
}

public class ViewModelBase : INotifyPropertyChanged

{
    public event PropertyChangedEventHandler PropertyChanged;
    public void RaisePropertyChangedEvent(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

public void SetFieldValue(String fieldName, Object classObj, Double value)

{
    PropertyInfo propertyInfo = classObj.GetType().GetProperty(fieldName);
    if (propertyInfo != null) propertyInfo.SetValue(classObj, value);
}

public Object GetFieldValue(String fieldName, Object classObj)
{
    PropertyInfo propertyInfo = classObj.GetType().GetProperty(fieldName);
    if (propertyInfo == null) return null;
    else
        return propertyInfo.GetValue(classObj);
}

public void SetFieldValue(String fieldName, Object classObj, String value)
{
    PropertyInfo propertyInfo = classObj.GetType().GetProperty(fieldName);
    if (propertyInfo != null) propertyInfo.SetValue(classObj, value);

}
}

public class SlateInfo : ViewModelBase

{

    private Guid _id = Guid.Empty;

    private String _name = String.Empty;

    private Boolean _isSelected = false;

    public Guid Id { get { return _id; } set { _id = value; RaisePropertyChangedEvent("Id"); } }

    public String Name { get { return _name; } set { _name = value; RaisePropertyChangedEvent("Name"); } }

    public Boolean IsSelected { get { return _isSelected; } set { _isSelected = value; RaisePropertyChangedEvent("IsSelected"); } }

}

     public class EquationTester : ViewModelBase, IMessage 
     {

private CanvasSelectionMode _selectionMode = CanvasSelectionMode.VirtualEquationElement;

public CanvasSelectionMode SelectionMode
{
    get { return _selectionMode; }
    set
    {
        _selectionMode = value;
        RaisePropertyChangedEvent("SelectionMode");
    }
}

public Dictionary<Guid, String> CanvasTabs = new Dictionary<Guid, String>()
{
{ new Guid("a4d4a35b-d85d-4ad1-a025-a5265bc58281"),"Slate #1" },
};

     public Boolean RenderText { get; set;} = false;

     public Boolean MathChange { get; set;} = false;

     private CanvasItemsExport _canvasItems = new CanvasItemsExport();

     public CanvasItemsExport CanvasItems { get { return _canvasItems; } set { _canvasItems = value; RaisePropertyChangedEvent("CanvasItems"); } }

     private ObservableCollection<SlateInfo> _slateInfos = new ObservableCollection<SlateInfo>();
     public ObservableCollection<SlateInfo> SlateInfos { get { return _slateInfos; } set { _slateInfos = value; RaisePropertyChangedEvent("SlateInfos"); } }
     private ICommand _changeSlateCommandIc = null;
     [XmlIgnore] public ICommand ChangeSlateCommandIc => _changeSlateCommandIc ?? (_changeSlateCommandIc = new RelayCommand<Object>(ChangeSlateCommandIcExecuted));
     public void ChangeSlateCommandIcExecuted(Object obj)
     {
         foreach (var x in SlateInfos) { x.IsSelected = false; }
         SelectedSlateInfo = (SlateInfo)obj;
         SelectedSlateInfo.IsSelected = true;
         foreach (var canvasItem in CanvasItems.Items) { canvasItem.IsVisible = false; }
         foreach (var canvasItem in CanvasItems.Items.Where(c => c.NodeId == SelectedSlateInfo.Id)) canvasItem.IsVisible = true;
     }

private SlateInfo _selectedSlateInfo = null;public SlateInfo SelectedSlateInfo { get { return _selectedSlateInfo; } set { _selectedSlateInfo = value; RaisePropertyChangedEvent("SelectedSlateInfo"); } }public event EventHandler<MathChangedEventArgs> MathChanged;
protected virtual void OnMathChanged(MathChangedEventArgs e)
{
    EventHandler <MathChangedEventArgs> handler = MathChanged;
    if (handler != null)
    {
        handler(this, e);
    }
}

private Boolean _showGridX = true;

private Boolean _showGridY = false;
private Boolean _showGridZ = false;
public Boolean ShowGridX { get { return _showGridX; } set { _showGridX = value; RaisePropertyChangedEvent("ShowGridX"); } }
public Boolean ShowGridY { get { return _showGridY; } set { _showGridY = value; RaisePropertyChangedEvent("ShowGridY"); } }
public Boolean ShowGridZ { get { return _showGridZ; } set { _showGridZ = value; RaisePropertyChangedEvent("ShowGridZ"); } }

        #region Commands


        #endregion

        #region Initialization Code

     //Initialization.cs

        #endregion

        public List<String> Messages { get;set; } = new List<String>();

        public const Double GoldenRatio = 1.61803398874989484820458683436;

        public const Double Mascheroni = .57721566490153286060651209008240243;

        public const Double Euler = 2.718281828459045235360;

        public Double GoldenRatioValue => GoldenRatio;

        public Double MascheroniValue => Mascheroni;

        public Double EulerValue => Euler;

        public long Factorial(int n)
        {
            if (n == 0)
            {
                return 1;
            }

            return n * Factorial(n - 1);
        }


        #region Constructor(s)

        public EquationTester()
        {
            ExecuteCodeBlock();
        }

        #endregion

        public int GCD(int p, int q)
        {
            if (q == 0) { return p; }
            int r = p % q;
            return GCD(q, r);
        }
        public String Ratio(int num1, int num2)
        {
            string oran = "";
            int gcd;
            int quotient = 0;

            while (num1 >= num2)
            {
                num1 = num1 - num2;
                quotient++;
            }

            gcd = GCD(num1, num2);

            //without using division finding ration of num1 i1
            int i1 = 1;

            while (gcd * i1 != num1)
            {
                i1++;
            }

            //without using division finding ration of num1 i2
            int i2 = 1;

            while (gcd * i2 != num2)
            {
                i2++;
            }

             if (quotient == 0)
                 oran = String.Concat(i1, " / ", i2);
             else
                 oran = String.Concat(quotient, " ", i1, " / ", i2);

             return oran;
        }

        #region Public Auto Properties


        #endregion

        #region Public Clr Properties



        #endregion

        private Model3DGroup _mainModel3DGroup = new Model3DGroup();
        public Model3DGroup MainModel3DGroup { get { return _mainModel3DGroup; } set { _mainModel3DGroup = value; RaisePropertyChangedEvent("MainModel3DGroup"); } }

        private Model3DGroup _textModel3DGroup = new Model3DGroup();
        public Model3DGroup TextModel3DGroup { get { return _textModel3DGroup; } set { _textModel3DGroup = value; RaisePropertyChangedEvent("TextModel3DGroup"); } }

        #region Files To Compile - Valid Equation Tests

        #endregion

        #region Sets


        #endregion

        #region Set Equations


        #endregion

        #region Extra Functions

        #endregion

        #region Default Summation

        private Double PerformSummation(Double start,Double end)
        {
             Double result = 0; 
             for (int i = Convert.ToInt16(start); i <= Convert.ToInt16(end); i++)
             {
                  result += i; 
             }

             return result; 
        }
        #endregion

        #region Public Functions - Update Equations

        public void UpdateEquations()
        {
        }

        #endregion

        public void ExecuteCodeBlock()
        {
     //ExecuteCodeBlock.cs

        }

        #region Public Functions - Evaluate Equations

        #endregion

     }
}

     #region Included Services 

     

     #endregion


