using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using Aitex.Core.RT.IOCore;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.Common.IOCore;
using MECF.Framework.Common.OperationCenter;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.OcrReaders.IOSS;
using MECF.Framework.UI.Client.ClientBase;
using OpenSEMI.ClientBase;
using OpenSEMI.ClientBase.IO;

namespace MECF.Framework.UI.Client.CenterViews.Maitenances.IO3
{
    /// <summary>
    /// 与IO2ViewModel的区别是，这个用Float类型的AI , AO 
    /// </summary>
    public class IO3ViewModel : UiViewModelBase, ISupportMultipleSystem
    {
        public Visibility DIVisibility
        {
            get { return DIs.Count > 0 ? Visibility.Visible : Visibility.Collapsed; }
        }
        public Visibility DOVisibility
        {
            get { return DOs.Count > 0 ? Visibility.Visible : Visibility.Collapsed; }
        }
        public Visibility AIVisibility
        {
            get { return AIs.Count > 0 ? Visibility.Visible : Visibility.Collapsed; }
        }
        public Visibility AOVisibility
        {
            get { return AOs.Count > 0 ? Visibility.Visible : Visibility.Collapsed; }
        }

        public int DIWidth
        {
            get { return (DIs.Count / 31 + 1) * 355; }
        }
        public int DOWidth
        {
            get { return (DOs.Count / 31 + 1) * 405; }
        }
        public int AIWidth
        {
            get { return (AIs.Count / 31 + 1) * 370; }
        }
        public int AOWidth
        {
            get { return (AOs.Count / 31 + 1) * 370; }
        }

        public ObservableCollection<IOItem<float>> AIs { get; private set; }
        public ObservableCollection<AOItemFloat> AOs { get; private set; }
        public ObservableCollection<IOItem<bool>> DIs { get; private set; }
        public ObservableCollection<IOItem<bool>> DOs { get; private set; }

        public ObservableCollection<IOItem<float>> AIsFilter { get; private set; }
        public ObservableCollection<AOItemFloat> AOsFilter { get; private set; }
        public ObservableCollection<IOItem<bool>> DIsFilter { get; private set; }
        public ObservableCollection<IOItem<bool>> DOsFilter { get; private set; }

        private string _diKey;
        private string _doKey;
        private string _aiKey;
        private string _aoKey;

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

            _diKey = $"{SystemName}.DIItemList";
            _doKey = $"{SystemName}.DOItemList";
            _aiKey = $"{SystemName}.AIItemList";
            _aoKey = $"{SystemName}.AOItemList";

            AIs = InitIOData<float>(IOType.AI, _aiKey);
            AOs = InitIOData(IOType.AO, _aoKey);
            DIs = InitIOData<bool>(IOType.DI, _diKey);
            DOs = InitIOData<bool>(IOType.DO, _doKey);

            AIsFilter = AIs;
            AOsFilter = AOs;
            DIsFilter = DIs;
            DOsFilter = DOs;


            _diKey = $"{SystemName}.DIList";
            _doKey = $"{SystemName}.DOList";
            _aiKey = $"{SystemName}.AIList";
            _aoKey = $"{SystemName}.AOList";
            Subscribe(_aiKey);
            Subscribe(_aoKey);
            Subscribe(_diKey);
            Subscribe(_doKey);
        }
        protected override void OnActivate()
        {
            base.OnActivate();
        }

        protected override void OnDeactivate(bool close)
        {
            base.OnDeactivate(close);
        }

        protected override void InvokeAfterUpdateProperty(Dictionary<string, object> data)
        {
            base.InvokeAfterUpdateProperty(data);

            if (data.ContainsKey(_aiKey) &&  data[_aiKey] != null)
            {
                var lstData = (List<NotifiableIoItem>)data[_aiKey];
                var dicValues = new Dictionary<string, float>();

                for (var i = 0; i < lstData.Count; i++)
                {
                    dicValues[lstData[i].Name] = lstData[i].FloatValue;
                }

                foreach (var item in AIs)
                {
                    if (dicValues.ContainsKey(item.Name))
                        item.Value = dicValues[item.Name];
                }
            }
            if (data.ContainsKey(_aoKey) && data[_aoKey] != null)
            {
                var lstData = (List<NotifiableIoItem>)data[_aoKey];
                var dicValues = new Dictionary<string, float>();

                for (var i = 0; i < lstData.Count; i++)
                {
                    dicValues[lstData[i].Name] = lstData[i].FloatValue;
                }

                foreach (IOItem<float> item in AOs)
                {
                    if (dicValues.ContainsKey(item.Name))
                        item.Value = dicValues[item.Name];
                }
            }

            if (data.ContainsKey(_diKey) && data[_diKey] != null)
            {
                var lstData = (List<NotifiableIoItem>)data[_diKey];
                var dicValues = new Dictionary<string, bool>();

                for (var i = 0; i < lstData.Count; i++)
                {
                    dicValues[lstData[i].Name] = lstData[i].BoolValue;
                }

                foreach (var item in DIs)
                {
                    if (dicValues.ContainsKey(item.Name))
                        item.Value = dicValues[item.Name];
                }
            }
            if (data.ContainsKey(_doKey) && data[_doKey] != null)
            {
                var lstData = (List<NotifiableIoItem>)data[_doKey];
                var dicValues = new Dictionary<string, bool>();

                for (var i = 0; i < lstData.Count; i++)
                {
                    dicValues[lstData[i].Name] = lstData[i].BoolValue;
                }

                foreach (var item in DOs)
                {
                    if (dicValues.ContainsKey(item.Name))
                        item.Value = dicValues[item.Name];
                }
            }
        }

        public void SetDO(IOItem<bool> doItem)
        {
            if (!DialogBox.Confirm(
                $"Please be attention, direct control DO is generally forbidden, Are you sure you want to do the operation?\r\n {doItem.DisplayName} = {!doItem.Value}",
                "Warning"))
                return;

            InvokeClient.Instance.Service.DoOperation("System.SetDoValue", doItem.Name, !doItem.Value);
        }

        public void SetAO(AOItemFloat AOItemFloat)
        {
            if (!DialogBox.Confirm(
                $"Please be attention, direct control AO is generally forbidden, Are you sure you want to do the operation?\r\n {AOItemFloat.DisplayName} = {AOItemFloat.NewValue}",
                "Warning" ))
                return;

            InvokeClient.Instance.Service.DoOperation("System.SetAoValueFloat", AOItemFloat.Name, AOItemFloat.NewValue);

            AOItemFloat.TextSaved = true;
        }

        private string GetDisplayName(NotifiableIoItem io)
        {
            if (!string.IsNullOrEmpty(io.Display_Zh))
            {
                return (io.Display_Zh.Length <= 10 ? io.Display_Zh : $"{io.Display_Zh.Substring(0, 10)}...") +
                       (string.IsNullOrEmpty(io.AltName) ? "" : $"({io.AltName})");
            }
            else
            {
                return (string.IsNullOrEmpty(io.Description) || io.Description.Length > 6)
                    ? io.Name.Substring(io.Name.IndexOf('.') + 1)
                    : io
                        .Name.Substring(io.Name.IndexOf('.') + 1) + " (" + io.Description + ")";
            }
        }

        private string GetToolTip(NotifiableIoItem io)
        {
            return $"Name: {io.Name}\r\nAddr: {io.Address}\r\nDescription: {io.Description}";
        }

        public ObservableCollection<IOItem<T>> InitIOData<T>(IOType type, string dataName)
        {
            //get the whole informations
            var da = new ObservableCollection<IOItem<T>>();

            if (type == IOType.DI)
            {
                var diList = QueryDataClient.Instance.Service.GetData(dataName);

                if (diList != null)
                {
                    var item = (List<NotifiableIoItem>)diList;
                    for (var i = 0; i < item.Count; i++)
                    {
                        var value = true;
                        if (value is T)
                        {
                            if(item[i].Visible)
                            {
                                da.Add(new IOItem<T>()
                                {
                                    Index = item[i].Index,
                                    Name = item[i].Name,
                                    DisplayName = GetDisplayName(item[i]),
                                    ToolTip = GetToolTip(item[i]),
                                    Value = (T)(object)item[i].BoolValue,
                                    Address = item[i].Address

                                });
                            }
                            
                        }
                    }
                }
            }

            if (type == IOType.DO)
            {
                var diList = QueryDataClient.Instance.Service.GetData(dataName);

                if (diList != null)
                {
                    var item = (List<NotifiableIoItem>)diList;
                    for (var i = 0; i < item.Count; i++)
                    {
                        var value = true;
                        if (value is T)
                        {
                            if (item[i].Visible)
                            {
                                da.Add(new IOItem<T>()
                                {
                                    Index = item[i].Index,
                                    Name = item[i].Name,
                                    DisplayName = GetDisplayName(item[i]),
                                    ToolTip = GetToolTip(item[i]),
                                    Value = (T)(object)item[i].BoolValue,
                                    Address = item[i].Address
                                });
                            }
                        }
                    }
                }
            }


            if (type == IOType.AI)
            {
                var diList = QueryDataClient.Instance.Service.GetData(dataName);

                if (diList != null)
                {
                    var item = (List<NotifiableIoItem>)diList;
                    for (var i = 0; i < item.Count; i++)
                    {
                        if (item[i].Visible)
                        {
                            da.Add(new IOItem<T>()
                            {
                                Index = item[i].Index,
                                Name = item[i].Name,
                                DisplayName = GetDisplayName(item[i]),
                                ToolTip = GetToolTip(item[i]),
                                Value = (T)(object)item[i].FloatValue,
                                Address = item[i].Address
                            });
                        }
                    }
                }
            }


            return da;
        }

        public ObservableCollection<AOItemFloat> InitIOData(IOType type, string dataName)
        {
            //get the whole informations
            var da = new ObservableCollection<AOItemFloat>();

            if (type == IOType.AO)
            {
                var diList = QueryDataClient.Instance.Service.GetData(dataName);

                if (diList != null)
                {
                    var item = (List<NotifiableIoItem>)diList;
                    for (var i = 0; i < item.Count; i++)
                    {
                        if (item[i].Visible)
                        {
                            da.Add(new AOItemFloat()
                            {
                                Index = item[i].Index,
                                Name = item[i].Name,
                                DisplayName = GetDisplayName(item[i]),
                                ToolTip = GetToolTip(item[i]),
                                Value = item[i].FloatValue,
                                Address = item[i].Address
                            });
                        }
                    }
                }
            }
            return da;
        }

        private string _currentCriteria = String.Empty;
        public string CurrentCriteria
        {
            get { return _currentCriteria; }
            set
            {
                if (value == _currentCriteria)
                    return;

                _currentCriteria = value;
                NotifyOfPropertyChange("CurrentCriteria");
                ApplyFilter();
            }
        }

        private void ApplyFilter()
        {
            var index = 0;

            if (int.TryParse(CurrentCriteria, out index))
            {
                DIsFilter = new ObservableCollection<IOItem<bool>>(
                DIs.Where(d => d.Index == index));

                DOsFilter = new ObservableCollection<IOItem<bool>>(
                DOs.Where(d => d.Index == index));

                AIsFilter = new ObservableCollection<IOItem<float>>(
                AIs.Where(d => d.Index == index));

                AOsFilter = new ObservableCollection<AOItemFloat>(
                AOs.Where(d => d.Index == index));
            }
            else
            {
                DIsFilter = new ObservableCollection<IOItem<bool>>(
                DIs.Where(d => d.DisplayName.IndexOf(CurrentCriteria, StringComparison.OrdinalIgnoreCase) >= 0));

                DOsFilter = new ObservableCollection<IOItem<bool>>(
                DOs.Where(d => d.DisplayName.IndexOf(CurrentCriteria, StringComparison.OrdinalIgnoreCase) >= 0));

                AIsFilter = new ObservableCollection<IOItem<float>>(
                AIs.Where(d => d.DisplayName.IndexOf(CurrentCriteria, StringComparison.OrdinalIgnoreCase) >= 0));

                AOsFilter = new ObservableCollection<AOItemFloat>(
                AOs.Where(d => d.DisplayName.IndexOf(CurrentCriteria, StringComparison.OrdinalIgnoreCase) >= 0));
            }
        }

        public void ClearFilter()
        {
            CurrentCriteria = "";
        }

    }
}
