namespace AvevaMemberListWindow
{
    #region Using
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using Aveva.ApplicationFramework;
    using Aveva.ApplicationFramework.Presentation;
    using Aveva.Pdms.Database;
    using Aveva.PDMS.Database.Filters;
    using Aveva.Pdms.Geometry;
    using Aveva.Pdms.Shared;
    using Aveva.Pdms.Utilities;
    #endregion

    /// <summary>
    /// Показать/скрыть список дочерних элементов
    /// </summary>
    public class MemberListCommand : Command
    {
        #region Свойства
        private WindowManager winMan;
        private DockedWindow window;
        private MemberList form;
        #endregion

        #region Конструктор
        public MemberListCommand()
        {
            this.winMan = Aveva.ApplicationFramework.Presentation.WindowManager.Instance;

            this.Key = "AvevaMemberListWindowAddin.ShowOrHideWindow";
            this.Description = "Список дочерних элементов";

            // создаём окно
            this.form = new MemberList();
            this.window = this.winMan.CreateDockedWindow("MemberListWindow", "Список дочерних элементов", this.form, DockedPosition.Floating);
            this.window.Title = "Список дочерних элементов";
            this.window.Tooltip = "Показывает сводку по дочерним элементам для текущего элемента";
            this.window.SaveLayout = true;

            // подписываемся на события
            this.winMan.WindowLayoutLoaded += this.OnWindowLayoutLoaded; // открытие окна
            this.window.Closed += this.OnWindowClosed; // закрытие окна
            CurrentElement.CurrentElementChanged += this.OnCurrentElementChanged; // изменение ce
        }
        #endregion

        #region Методы
        /// <summary>
        /// Обновить список элементов
        /// </summary>
        private void Update()
        {
            this.form.Clear();

            this.form.AddItems(this.GetElements(CurrentElement.Element).OrderBy(x => x.Type).ThenBy(x => x.SpRef).ToList());
        }

        /// <summary>
        /// Сбор дочерних элементов
        /// </summary>
        /// <param name="elem">Элемент</param>
        private List<MemberListItem> GetElements(DbElement elem)
        {
            List<MemberListItem> result = new List<MemberListItem>();

            DBElementCollection elems = new DBElementCollection(elem);

            foreach (DbElement dbEle in elems)
            {
                string type = dbEle.GetAsString(DbAttributeInstance.FULL);
                string spRefName = string.Empty;
                double weight = 0;
                double count = 0;
                string description = string.Empty;

                if (dbEle.IsAttributeValid(DbAttributeInstance.SPRE))
                {
                    DbElement spRefEle = dbEle.GetElement(DbAttributeInstance.SPRE);

                    if (spRefEle.IsValid)
                    {
                        spRefName = spRefEle.GetAsString(DbAttributeInstance.NAME);

                        if (spRefEle.IsAttributeValid(DbAttributeInstance.CMPR))
                        {
                            DbElement cmpRefEle = spRefEle.GetElement(DbAttributeInstance.CMPR);

                            if (cmpRefEle.IsValid)
                            {
                                if (type.Equals(DbElementTypeInstance.TUBING.Name) || type.Equals(DbElementTypeInstance.BEND.Name))
                                {
                                    if (cmpRefEle.IsAttributeValid(DbAttributeInstance.UWEI))
                                        Double.TryParse(cmpRefEle.GetAsString(DbAttributeInstance.UWEI)
                                            .Replace('.', ',').Replace('(', ' ').Replace(')', ' ').Trim(), out weight);
                                    else
                                        Double.TryParse(cmpRefEle.GetAsString(DbAttributeInstance.CWEI)
                                            .Replace('.', ',').Replace('(', ' ').Replace(')', ' ').Trim(), out weight);
                                }
                                else
                                {
                                    if (cmpRefEle.IsAttributeValid(DbAttributeInstance.CWEI))
                                        Double.TryParse(cmpRefEle.GetAsString(DbAttributeInstance.CWEI)
                                            .Replace('.', ',').Replace('(', ' ').Replace(')', ' ').Trim(), out weight);
                                    else
                                        Double.TryParse(cmpRefEle.GetAsString(DbAttributeInstance.UWEI)
                                            .Replace('.', ',').Replace('(', ' ').Replace(')', ' ').Trim(), out weight);
                                }
                            }
                        }

                        DbElement detRefEle = spRefEle.GetElement(DbAttributeInstance.DETR);

                        if (detRefEle.IsValid)
                            description = detRefEle.GetAsString(DbAttributeInstance.RTEX);
                    }
                }

                // трубы и изгибы считаются отдельно в мм
                if (type.Equals(DbElementTypeInstance.TUBING.Name))
                    Double.TryParse(dbEle.GetAsString(DbAttributeInstance.ITLE).Replace("mm", string.Empty).Replace('.', ','), out count);
                else if (type.Equals(DbElementTypeInstance.BEND.Name))
                    Double.TryParse(dbEle.GetAsString(DbAttributeInstance.FITLEN).Replace("mm", string.Empty).Replace('.', ','), out count);
                else
                    count = 1;

                // если такой элемент в коллекции уже есть, приплюсуем к нему, иначе добавляем новый элемент
                if (result.Exists(x => x.Type == type && x.SpRef == spRefName))
                {
                    MemberListItem foundItem = result.Find(x => x.Type == type && x.SpRef == spRefName);
                    foundItem.Count += count;
                }
                else
                    result.Add(new MemberListItem(type, spRefName, weight, count, description));
            }

            return result;
        }
        #endregion

        #region Command
        /// <summary>
        /// Вызов команды
        /// </summary>
        public override void Execute()
        {
            if (this.Checked)
            {
                this.window.Show();

                if (!this.window.Visible)
                    return;

                this.Update();

                this.Checked = false;
            }
            else
            {
                this.window.Hide();
                this.Checked = true;
            }
        }
        #endregion

        #region События
        /// <summary>
        /// При изменении CE
        /// </summary>
        public void OnCurrentElementChanged(object sender, CurrentElementChangedEventArgs e)
        {
            if (!this.window.Visible)
                return;

            this.Update();
        }

        /// <summary>
        /// При открытии окна
        /// </summary>
        private void OnWindowLayoutLoaded(object sender, EventArgs e)
        {
            this.Checked = true;
        }

        /// <summary>
        /// При закрытии окна
        /// </summary>
        private void OnWindowClosed(object sender, EventArgs e)
        {
            this.Checked = true;
        }
        #endregion
    }
}
