using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.DiagramDesigner.Models;
using AIStudio.Wpf.DiagramDesigner.Services;

namespace AIStudio.Wpf.Logical.ViewModels
{
    public abstract class LogicalGateItemViewModel : LogicalGateItemViewModelBase
    {
        protected IUIVisualizerService visualiserService;
        public LogicalGateItemViewModel(LogicalType logicalType) : this(null, logicalType)
        {

        }

        public LogicalGateItemViewModel(IDiagramViewModel root, LogicalType logicalType) : base(root, logicalType)
        {

        }

        public LogicalGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public LogicalGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        public override SelectableItemBase GetSerializableObject()
        {
            return new LogicalGateDesignerItemBase(this);
        }

        protected override void Init(IDiagramViewModel root, bool initNew)
        {
            base.Init(root, initNew);

            visualiserService = ApplicationServicesProvider.Instance.Provider.VisualizerService;
        }

        protected override void InitNew()
        {
            base.InitNew();

            ColorViewModel.FillColor.Color = Colors.Orange;
        }

        protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase)
        {
            base.LoadDesignerItemViewModel(designerbase);

            if (designerbase is LogicalGateDesignerItemBase designer)
            {
                this.Value = designer.Value;
            }
        }

        protected override void ExecuteEditCommand(object parameter)
        {
            if (LogicalType == LogicalType.Constant)
            {
                ValueDesignerItemData data = new ValueDesignerItemData(Value);
                if (visualiserService.ShowDialog(data) == true)
                {
                    this.Value = data.Value;
                }
            }
            else
            {
                LogicalGateItemData data = new LogicalGateItemData(Input.Values);
                if (visualiserService.ShowDialog(data) == true)
                {

                }
            }
        }
    }

    public class AddGateItemViewModel : LogicalGateItemViewModel
    {
        public AddGateItemViewModel() : this(null)
        {
        }

        public AddGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.ADD)
        {
        }

        public AddGateItemViewModel(IDiagramViewModel root, LogicalGateDesignerItemBase designer) : base(root, designer)
        {
        }

        public AddGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        public override bool EnableAddInput
        {
            get;
        } = true;

        public override bool EnableAddOutput
        {
            get;
        } = false;

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Input.Values.Select(p => p.ConnectorValue).Sum();
            }
            base.CalculateOutput();
        }
    }

    public class SubtractGateItemViewModel : LogicalGateItemViewModel
    {
        public SubtractGateItemViewModel() : this(null)
        {
        }

        public SubtractGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.SUB)
        {
        }

        public SubtractGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {
        }

        public SubtractGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override bool EnableAddInput
        {
            get;
        } = true;

        public override bool EnableAddOutput
        {
            get;
        } = false;

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                var first = Input.Values.Select(p => p.ConnectorValue).FirstOrDefault();
                var second = Input.Values.Where((value, index) => index != 0).Select(p => p.ConnectorValue).Sum();
                output.Value.ConnectorValue = first - second;
            }
            base.CalculateOutput();
        }
    }

    public class MultiplyGateItemViewModel : LogicalGateItemViewModel
    {
        public MultiplyGateItemViewModel() : this(null)
        {
        }

        public MultiplyGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.MUL)
        {
        }

        public MultiplyGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {
        }

        public MultiplyGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override bool EnableAddInput
        {
            get;
        } = true;

        public override bool EnableAddOutput
        {
            get;
        } = false;

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                double result = 1;
                foreach (var input in Input.Values)
                {
                    result *= input.ConnectorValue;
                }
                output.Value.ConnectorValue = result;
            }
            base.CalculateOutput();
        }
    }

    public class DivideGateItemViewModel : LogicalGateItemViewModel
    {

        public DivideGateItemViewModel() : this(null)
        {
        }

        public DivideGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.DIV)
        {
        }

        public DivideGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {
        }

        public DivideGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override bool EnableAddInput
        {
            get;
        } = true;

        public override bool EnableAddOutput
        {
            get;
        } = false;

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                double result = Input.Values.Select(p => p.ConnectorValue).FirstOrDefault();
                foreach (var input in Input.Values.Where((value, index) => index != 0))
                {
                    result /= input.ConnectorValue;
                }
                output.Value.ConnectorValue = result;
            }
            base.CalculateOutput();
        }
    }

    public class AverageGateItemViewModel : LogicalGateItemViewModel
    {
        public AverageGateItemViewModel() : this(null)
        {

        }

        public AverageGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.AVE)
        {
        }

        public AverageGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public AverageGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override bool EnableAddInput
        {
            get;
        } = true;

        public override bool EnableAddOutput
        {
            get;
        } = false;

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Input.Values.Select(p => p.ConnectorValue).Average();
            }
            base.CalculateOutput();
        }
    }

    public class MODGateItemViewModel : LogicalGateItemViewModel
    {
        public MODGateItemViewModel() : this(null)
        {

        }

        public MODGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.MOD)
        {
        }

        public MODGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public MODGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Input[0].ConnectorValue % Input[1].ConnectorValue;
            }
            base.CalculateOutput();
        }
    }

    public class ANDGateItemViewModel : LogicalGateItemViewModel
    {
        public ANDGateItemViewModel() : this(null)
        {

        }

        public ANDGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.AND)
        {
        }

        public ANDGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public ANDGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Convert.ToInt32(Input[0].ConnectorValue) & Convert.ToInt32(Input[1].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class ORGateItemViewModel : LogicalGateItemViewModel
    {
        public ORGateItemViewModel() : this(null)
        {

        }

        public ORGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.OR)
        {
        }

        public ORGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public ORGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Convert.ToInt32(Input[0].ConnectorValue) | Convert.ToInt32(Input[1].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class XORGateItemViewModel : LogicalGateItemViewModel
    {
        public XORGateItemViewModel() : this(null)
        {

        }

        public XORGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.XOR)
        {
        }

        public XORGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public XORGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Convert.ToInt32(Convert.ToInt32(Input[0].ConnectorValue) ^ Convert.ToInt32(Input[1].ConnectorValue));
            }
            base.CalculateOutput();
        }
    }

    public class NOTGateItemViewModel : LogicalGateItemViewModel
    {
        public NOTGateItemViewModel() : this(null)
        {

        }

        public NOTGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.NOT)
        {
        }

        public NOTGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public NOTGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                if (Input[0].ConnectorValueType == DiagramDesigner.ConnectorValueType.Bool)
                {
                    output.Value.ConnectorValue = Convert.ToInt32(!Convert.ToBoolean(Input[0].ConnectorValue));
                    output.Value.ConnectorValueType = DiagramDesigner.ConnectorValueType.Bool;
                }
                else
                {
                    output.Value.ConnectorValue = ~Convert.ToInt32(Input[0].ConnectorValue);
                    output.Value.ConnectorValueType = DiagramDesigner.ConnectorValueType.Int;
                }
            }
            base.CalculateOutput();
        }
    }

    public class SHLGateItemViewModel : LogicalGateItemViewModel
    {
        public SHLGateItemViewModel() : this(null)
        {

        }

        public SHLGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.SHL)
        {
        }

        public SHLGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public SHLGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Convert.ToInt32(Input[0].ConnectorValue) << Convert.ToInt32(Input[1].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class SHRGateItemViewModel : LogicalGateItemViewModel
    {
        public SHRGateItemViewModel() : this(null)
        {

        }

        public SHRGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.SHR)
        {
        }

        public SHRGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public SHRGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Convert.ToInt32(Input[0].ConnectorValue) >> Convert.ToInt32(Input[1].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class ROLGateItemViewModel : LogicalGateItemViewModel
    {
        public ROLGateItemViewModel() : this(null)
        {

        }

        public ROLGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.ROL)
        {
        }

        public ROLGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public ROLGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = (Convert.ToInt32(Input[0].ConnectorValue) << Convert.ToInt32(Input[1].ConnectorValue)) | (Convert.ToInt32(Input[0].ConnectorValue) >> 32 - Convert.ToInt32(Input[1].ConnectorValue));
            }
            base.CalculateOutput();
        }
    }

    public class RORGateItemViewModel : LogicalGateItemViewModel
    {
        public RORGateItemViewModel() : this(null)
        {

        }

        public RORGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.ROR)
        {
        }

        public RORGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public RORGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Int };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = (Convert.ToInt32(Input[0].ConnectorValue) >> Convert.ToInt32(Input[1].ConnectorValue)) | (Convert.ToInt32(Input[0].ConnectorValue) << 32 - Convert.ToInt32(Input[1].ConnectorValue));
            }
            base.CalculateOutput();
        }
    }

    public class SELGateItemViewModel : LogicalGateItemViewModel
    {
        public SELGateItemViewModel() : this(null)
        {

        }

        public SELGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.SEL)
        {
        }

        public SELGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public SELGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null, 0);
            ExecuteAddInput(null, 1);
            ExecuteAddInput(null, 2);
            ExecuteAddOutput(null, 0);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Bool, ConnectorValueType.Real, ConnectorValueType.Real };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = (Input[0].ConnectorValue == output.Key) ? Input[1].ConnectorValue : Input[2].ConnectorValue;
            }
            base.CalculateOutput();
        }
    }

    public class MAXGateItemViewModel : LogicalGateItemViewModel
    {
        public MAXGateItemViewModel() : this(null)
        {

        }

        public MAXGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.MAX)
        {
        }

        public MAXGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public MAXGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override bool EnableAddInput
        {
            get;
        } = true;

        public override bool EnableAddOutput
        {
            get;
        } = false;

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Input.Values.Select(p => p.ConnectorValue).Max();
            }
            base.CalculateOutput();
        }
    }

    public class MINGateItemViewModel : LogicalGateItemViewModel
    {
        public MINGateItemViewModel() : this(null)
        {

        }

        public MINGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.MIN)
        {
        }

        public MINGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public MINGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override bool EnableAddInput
        {
            get;
        } = true;

        public override bool EnableAddOutput
        {
            get;
        } = false;

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Input.Values.Select(p => p.ConnectorValue).Min();
            }
            base.CalculateOutput();
        }
    }

    public class LIMITGateItemViewModel : LogicalGateItemViewModel
    {
        public LIMITGateItemViewModel() : this(null)
        {

        }

        public LIMITGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.LIMIT)
        {
        }

        public LIMITGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public LIMITGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {
                return new List<ConnectorValueType>() { ConnectorValueType.Real };
            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = (Input[0].ConnectorValue > Input[1].ConnectorValue) ? Input[1].ConnectorValue : Input[0].ConnectorValue;
            }
            base.CalculateOutput();
        }
    }

    public class GTGateItemViewModel : LogicalGateItemViewModel
    {
        public GTGateItemViewModel() : this(null)
        {

        }

        public GTGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.GT)
        {
        }

        public GTGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public GTGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Bool };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = (Input[0].ConnectorValue > Input[1].ConnectorValue) ? 1 : 0;
            }

            base.CalculateOutput();
        }
    }

    public class LTGateItemViewModel : LogicalGateItemViewModel
    {
        public LTGateItemViewModel() : this(null)
        {

        }

        public LTGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.LT)
        {
        }

        public LTGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public LTGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Bool };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = (Input[0].ConnectorValue < Input[1].ConnectorValue) ? 1 : 0;
            }
        }
    }

    public class GEGateItemViewModel : LogicalGateItemViewModel
    {
        public GEGateItemViewModel() : this(null)
        {

        }

        public GEGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.GE)
        {
        }

        public GEGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public GEGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Bool };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = (Input[0].ConnectorValue >= Input[1].ConnectorValue) ? 1 : 0;
            }
            base.CalculateOutput();
        }
    }

    public class LEGateItemViewModel : LogicalGateItemViewModel
    {
        public LEGateItemViewModel() : this(null)
        {

        }

        public LEGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.LE)
        {
        }

        public LEGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public LEGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Bool };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = (Input[0].ConnectorValue <= Input[1].ConnectorValue) ? 1 : 0;
            }
            base.CalculateOutput();
        }
    }

    public class EQGateItemViewModel : LogicalGateItemViewModel
    {
        public EQGateItemViewModel() : this(null)
        {

        }

        public EQGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.EQ)
        {
        }

        public EQGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public EQGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Bool };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = (Input[0].ConnectorValue == Input[1].ConnectorValue) ? 1 : 0;
            }
            base.CalculateOutput();
        }
    }

    public class NEGateItemViewModel : LogicalGateItemViewModel
    {
        public NEGateItemViewModel() : this(null)
        {

        }

        public NEGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.NE)
        {
        }

        public NEGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public NEGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Bool };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = (Input[0].ConnectorValue != Input[1].ConnectorValue) ? 1 : 0;
            }
            base.CalculateOutput();
        }

    }

    public class ABSGateItemViewModel : LogicalGateItemViewModel
    {
        public ABSGateItemViewModel() : this(null)
        {

        }

        public ABSGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.ABS)
        {
        }

        public ABSGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public ABSGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Abs(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class SQRTGateItemViewModel : LogicalGateItemViewModel
    {
        public SQRTGateItemViewModel() : this(null)
        {

        }

        public SQRTGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.SQRT)
        {
        }

        public SQRTGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public SQRTGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Sqrt(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class LNGateItemViewModel : LogicalGateItemViewModel
    {
        public LNGateItemViewModel() : this(null)
        {

        }

        public LNGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.LN)
        {
        }

        public LNGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public LNGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Log10(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class LOGGateItemViewModel : LogicalGateItemViewModel
    {
        public LOGGateItemViewModel() : this(null)
        {

        }

        public LOGGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.LOG)
        {
        }

        public LOGGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public LOGGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Log(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class EXPGateItemViewModel : LogicalGateItemViewModel
    {
        public EXPGateItemViewModel() : this(null)
        {

        }

        public EXPGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.EXP)
        {
        }

        public EXPGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public EXPGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Exp(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class SINGateItemViewModel : LogicalGateItemViewModel
    {
        public SINGateItemViewModel() : this(null)
        {

        }

        public SINGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.SIN)
        {
        }

        public SINGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public SINGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Sin(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class COSGateItemViewModel : LogicalGateItemViewModel
    {
        public COSGateItemViewModel() : this(null)
        {

        }

        public COSGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.COS)
        {
        }

        public COSGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public COSGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Cos(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class TANGateItemViewModel : LogicalGateItemViewModel
    {
        public TANGateItemViewModel() : this(null)
        {

        }

        public TANGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.TAN)
        {
        }

        public TANGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public TANGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Tan(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class ASINGateItemViewModel : LogicalGateItemViewModel
    {
        public ASINGateItemViewModel() : this(null)
        {

        }

        public ASINGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.ASIN)
        {
        }

        public ASINGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public ASINGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Asin(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class ACOSGateItemViewModel : LogicalGateItemViewModel
    {
        public ACOSGateItemViewModel() : this(null)
        {

        }

        public ACOSGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.ACOS)
        {
        }

        public ACOSGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public ACOSGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Acos(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class ATANGateItemViewModel : LogicalGateItemViewModel
    {
        public ATANGateItemViewModel() : this(null)
        {

        }

        public ATANGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.ATAN)
        {
        }

        public ATANGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public ATANGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Atan(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class EXPTGateItemViewModel : LogicalGateItemViewModel
    {
        public EXPTGateItemViewModel() : this(null)
        {

        }

        public EXPTGateItemViewModel(IDiagramViewModel root) : base(root, LogicalType.EXPT)
        {
        }

        public EXPTGateItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public EXPTGateItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Math.Exp(Input[0].ConnectorValue);
            }
            base.CalculateOutput();
        }
    }

    public class ConstantDesignerItemViewModel : LogicalGateItemViewModel
    {
        public ConstantDesignerItemViewModel() : this(null)
        {

        }

        public ConstantDesignerItemViewModel(IDiagramViewModel root) : base(root, LogicalType.Constant)
        {
            ItemHeight = 28;
        }

        public ConstantDesignerItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public ConstantDesignerItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void GetInput()
        {
            //无输入
        }

        public override void CalculateOutput()
        {
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = Value;
            }
            base.CalculateOutput();
        }
    }

    public class InputItemViewModel : LogicalGateItemViewModel
    {
        public InputItemViewModel() : this(null)
        {
        }

        public InputItemViewModel(IDiagramViewModel root) : base(root, LogicalType.Input)
        {
            ItemHeight = 28;
        }

        public InputItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public InputItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase)
        {
            base.LoadDesignerItemViewModel(designerbase);

            if (designerbase is LogicalGateDesignerItemBase designer)
            {
                this.Value = designer.Value;
                LinkPoint = LogicalService.LinkPoint.FirstOrDefault(p => p.Id.ToString() == designer.Icon);  //不想新增字段了，就用这个Icon保存自定义测点的Id吧。
                if (LinkPoint != null)
                {
                    LinkPoint.Value = designer.Value;
                }
            }
        }

        private LinkPoint _linkPoint;
        public LinkPoint LinkPoint
        {
            get
            {
                return _linkPoint;
            }
            set
            {
                if (SetProperty(ref _linkPoint, value))
                {
                    Icon = _linkPoint?.Id.ToString();//不想新增字段了，就用这个Icon保存自定义测点的Id吧。
                    Text = _linkPoint?.Name;
                }
            }
        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddOutput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void GetInput()
        {
            //无输入
        }

        public override void CalculateOutput()
        {
            if (LinkPoint != null)
            {
                foreach (var output in Output)
                {
                    output.Value.ConnectorValue = LinkPoint.Value;
                }
            }
            base.CalculateOutput();
        }

        protected override void ExecuteEditCommand(object parameter)
        {
            LinkPointDesignerItemData data = new LinkPointDesignerItemData(LinkPoint);
            if (visualiserService.ShowDialog(data) == true)
            {
                this.LinkPoint = data.LinkPoint;
            }
        }
    }

    public class OutputItemViewModel : LogicalGateItemViewModel
    {
        public OutputItemViewModel() : this(null)
        {

        }

        public OutputItemViewModel(IDiagramViewModel root) : base(root, LogicalType.Output)
        {
            ItemHeight = 28;
        }

        public OutputItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public OutputItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase)
        {
            base.LoadDesignerItemViewModel(designerbase);

            if (designerbase is LogicalGateDesignerItemBase designer)
            {

                this.Value = designer.Value;
                LinkPoint = LogicalService.LinkPoint.FirstOrDefault(p => p.Id.ToString() == designer.Icon);  //不想新增字段了，就用这个Icon保存自定义测点的Id吧。
                if (LinkPoint != null)
                {
                    LinkPoint.Value = designer.Value;
                }
            }
        }

        private LinkPoint _linkPoint;
        public LinkPoint LinkPoint
        {
            get
            {
                return _linkPoint;
            }
            set
            {
                if (SetProperty(ref _linkPoint, value))
                {
                    Icon = _linkPoint?.Id.ToString();//不想新增字段了，就用这个Icon保存自定义测点的Id吧。
                    Text = _linkPoint?.Name;
                }
            }
        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddInput(null);
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override void CalculateOutput()
        {
            var first = Input.Values.FirstOrDefault();
            Value = first.ConnectorValue;
            LinkPoint.Value = first.ConnectorValue;
            foreach (var output in Output)
            {
                output.Value.ConnectorValue = first.ConnectorValue;
                output.Value.ConnectorValueType = first.ConnectorValueType;
            }
            base.CalculateOutput();
        }

        protected override void ExecuteEditCommand(object parameter)
        {
            LinkPointDesignerItemData data = new LinkPointDesignerItemData(LinkPoint);
            if (visualiserService.ShowDialog(data) == true)
            {
                this.LinkPoint = data.LinkPoint;
            }
        }
    }

    public class TimerDesignerItemViewModel : LogicalGateItemViewModel
    {
        private System.Timers.Timer readDataTimer = new System.Timers.Timer();
        public Action Do;

        public TimerDesignerItemViewModel() : this(null)
        {

        }

        public TimerDesignerItemViewModel(IDiagramViewModel root) : base(root, LogicalType.Time)
        {
            ItemHeight = 32;
            ItemWidth = 32;
            Value = 1;
            Start();
            BuildMenuOptions();
        }

        public TimerDesignerItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {
            BuildMenuOptions();
        }

        public TimerDesignerItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {
            BuildMenuOptions();
        }

        protected override void Init(IDiagramViewModel root, bool initNew)
        {
            base.Init(root, initNew);

            MenuItemCommand = new SimpleCommand(Command_Enable, ExecuteMenuItemCommand);
            readDataTimer.Elapsed += timeCycle;
            readDataTimer.Interval = 1000;
        }

        protected override void InitNew()
        {
            base.InitNew();

            ClearConnectors();
            ExecuteAddOutput(null);
        }

        protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase)
        {
            base.LoadDesignerItemViewModel(designerbase);

            if (IsEnabled)
            {
                Start();
            }
            else
            {
                Stop();
            }
        }

        public override List<ConnectorValueType> ValueTypeInput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        public override List<ConnectorValueType> ValueTypeOutput
        {
            get
            {

                return new List<ConnectorValueType>() { ConnectorValueType.Real };

            }
        }

        private void Start()
        {
            IsEnabled = true;
            Output[0].ColorViewModel.FillColor.Color = Colors.Green;
            readDataTimer.Start();
        }

        private void Stop()
        {
            IsEnabled = false;
            Output[0].ColorViewModel.FillColor.Color = Colors.Red;
            readDataTimer.Stop();
        }

        private void ExecuteMenuItemCommand(object obj)
        {
            if ((obj as CinchMenuItem).IsChecked == true)
            {
                Start();
            }
            else
            {
                Stop();
            }
        }

        public SimpleCommand MenuItemCommand
        {
            get; private set;
        }
        private void BuildMenuOptions()
        {
            menuOptions = new ObservableCollection<CinchMenuItem>();
            CinchMenuItem menuItem = new CinchMenuItem();
            menuItem.Text = "启动";
            menuItem.IsCheckable = true;
            menuItem.IsChecked = IsEnabled;
            menuItem.Command = MenuItemCommand;
            menuItem.CommandParameter = menuItem;
            menuOptions.Add(menuItem);
        }

        protected override void ExecuteEditCommand(object parameter)
        {
            ValueDesignerItemData data = new ValueDesignerItemData(Value);
            if (visualiserService.ShowDialog(data) == true)
            {
                this.Value = data.Value;
                readDataTimer.Interval = this.Value * 1000;
            }
        }

        private void timeCycle(object sender, EventArgs e)
        {
            Output.FirstOrDefault().Value.ConnectorValue += Value;
            if (Do != null)
            {
                Do();
            }
        }

        public override void Dispose()
        {
            base.Dispose();
            readDataTimer.Stop();
            readDataTimer.Dispose();
        }

    }
}
