#region COPYRIGHT
//
//     THIS IS GENERATED BY TEMPLATE
//     
//     AUTHOR  :     ROYE
//     DATE       :     2010
//
//     COPYRIGHT (C) 2010, TIANXIAHOTEL TECHNOLOGIES CO., LTD. ALL RIGHTS RESERVED.
//
#endregion

using System;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;


namespace TX.Framework.WindowUI.Controls
{
    public class TreeListViewItemCollection : CollectionBase
    {
        private delegate void VoidHandlerSortOrder(SortOrder value);

        private bool _Sortable = true;
        private ITreeListViewItemComparer _Comparer = new TreeListViewItemCollectionComparer(SortOrder.Ascending);
        private TreeListView _Owner;
        private TreeListViewItem _Parent;

        public TreeListViewEventHandler ItemAdded;
        public TreeListViewEventHandler ItemRemoved;

        public TreeListViewItemCollection(TreeListView owner)
        {
            _Owner = owner;
        }

        public TreeListViewItemCollection(TreeListViewItem parent)
        {
            _Parent = parent;
        }

        public TreeListViewItemCollection()
        {
        }

        protected virtual void OnItemAdded(TreeListViewEventArgs e)
        {
            if (ItemAdded != null)
            {
                ItemAdded(this, e);
            }
        }

        protected virtual void OnItemRemoved(TreeListViewEventArgs e)
        {
            if (ItemRemoved != null)
            {
                ItemRemoved(this, e);
            }
        }

        public TreeListViewItem[] ToArray()
        {
            if (TreeListView != null)
            {
                if (TreeListView.InvokeRequired)
                {
                    throw new Exception("Invoke required");
                }
            }
            int size = this.Count;
            TreeListViewItem[] items = new TreeListViewItem[size];
            for (int i = 0; i < size; i++)
            {
                items[i] = this[i];
            }
            return items;
        }

        public void Sort(bool recursively)
        {
            if (TreeListView != null) TreeListView.BeginUpdate();
            SortInternal(recursively);
            if (TreeListView != null) TreeListView.EndUpdate();
        }

        internal void SortInternal(bool recursively)
        {
            if (TreeListView != null)
            {
                if (TreeListView.InvokeRequired)
                {
                    throw (new Exception("Invoke required"));
                }
            }
            if (_Sortable)
            {
                // Gets an array of the items
                TreeListViewItem[] thisarray = ToArray();
                // Removes the items
                ClearInternal();
                // Adds the items
                foreach (TreeListViewItem item in thisarray)
                {
                    Add(item);
                }
            }
            if (recursively)
            {
                foreach (TreeListViewItem item in this)
                {
                    item.Items.SortInternal(true);
                }
            }
        }

        public virtual bool Contains(TreeListViewItem item)
        {
            if (TreeListView != null)
            {
                if (TreeListView.InvokeRequired)
                {
                    throw (new Exception("Invoke required"));
                }
            }
            bool founded = false;
            foreach (TreeListViewItem elt in this)
            {
                if (item == elt)
                {
                    founded = true;
                    break;
                }
            }
            return founded;
        }

        private bool ListViewContains(TreeListViewItem item)
        {
            if (TreeListView == null)
            {
                return false;
            }
            if (TreeListView.InvokeRequired)
            {
                throw new Exception("Invoke required");
            }
            ListView listview = (ListView)TreeListView;
            ListViewItem listviewitem = (ListViewItem)item;
            try
            {
                foreach (ListViewItem temp in listview.Items)
                {
                    if (temp == listviewitem) return true;
                }
            }
            catch { }
            return false;
        }

        public virtual int Add(TreeListViewItem item)
        {
            if (TreeListView != null)
            {
                if (TreeListView.InvokeRequired)
                {
                    throw (new Exception("Invoke required"));
                }
            }
            // Do not add the item if the collection owns a TreeListView recursively
            // and the item already owns a TreeListView
            if (TreeListView != null && item.ListView != null)
            {
                throw new Exception("The Item is already in a TreeListView");
            }
            int index = GetInsertCollectionIndex(item);
            if (index == -1) return -1;
            if (Parent != null) item.SetParent(Parent);
            item.Items.Comparer = this.Comparer;
            int treeListViewIndex = GetInsertTreeListViewIndex(item, index);
            // Insert in the ListView
            if (treeListViewIndex > -1)
            {
                ListView listview = (ListView)TreeListView;
                listview.Items.Insert(treeListViewIndex, (ListViewItem)item);
                if (item.IsExpanded)
                {
                    item.Expand();
                }
                item.SetIndentation();
            }
            // Insert in this collection
            if (index > -1)
            {
                List.Insert(index, item);
            }
            if (index > -1)
            {
                OnItemAdded(new TreeListViewEventArgs(item, TreeListViewAction.Unknown));
            }
            if (Count == 1 && TreeListView != null && Parent != null)
            {
                if (Parent.Visible)
                {
                    Parent.Redraw();
                }
            }
            return index;
        }

        public virtual TreeListViewItem Add(string value, int imageIndex)
        {
            TreeListViewItem item = new TreeListViewItem(value, imageIndex);
            Add(item);
            return item;
        }

        public virtual TreeListViewItem Add(string value)
        {
            TreeListViewItem item = new TreeListViewItem(value);
            Add(item);
            return item;
        }

        public void AddRange(TreeListViewItemCollection collection)
        {
            if (TreeListView != null) TreeListView.BeginUpdate();
            AddRangeInternal(collection);
            if (TreeListView != null) TreeListView.BeginUpdate();
        }

        internal void AddRangeInternal(TreeListViewItemCollection collection)
        {
            foreach (TreeListViewItem item in collection)
            {
                Add(item);
            }
        }

        public new void Clear()
        {
            TreeListView treelistview = this.TreeListView;
            if (treelistview != null) treelistview.BeginUpdate();
            ClearInternal();
            if (treelistview != null) treelistview.EndUpdate();
        }

        internal void ClearInternal()
        {
            if (TreeListView != null)
            {
                if (TreeListView.InvokeRequired)
                {
                    throw (new Exception("Invoke required"));
                }
            }
            while (this.Count > 0) this.RemoveAtInternal(0);
        }

        public virtual void Remove(TreeListViewItem item)
        {
            TreeListView treelistview = this.TreeListView;
            if (treelistview != null) treelistview.BeginUpdate();
            RemoveInternal(item);
            if (treelistview != null) treelistview.EndUpdate();
        }

        internal void RemoveInternal(TreeListViewItem item)
        {
            if (TreeListView != null)
            {
                if (TreeListView.InvokeRequired)
                {
                    throw (new Exception("Invoke required"));
                }
            }
            int index = GetIndexOf(item);
            if (index == -1) return;
            RemoveAtInternal(index);
        }

        public int GetIndexOf(TreeListViewItem item)
        {
            if (TreeListView != null)
            {
                if (TreeListView.InvokeRequired)
                {
                    throw new Exception("Invoke required");
                }
            }
            int index = -1;
            for (int i = 0; i < this.Count; i++)
            {
                if (this[i] == item)
                {
                    index = i;
                    break;
                }
            }
            return index;
        }

        public new void RemoveAt(int index)
        {
            TreeListView treelistview = this.TreeListView;
            if (treelistview != null) treelistview.BeginUpdate();
            RemoveAtInternal(index);
            if (treelistview != null) treelistview.EndUpdate();
        }

        internal void RemoveAtInternal(int index)
        {
            if (TreeListView != null)
            {
                if (TreeListView.InvokeRequired)
                {
                    throw new Exception("Invoke required");
                }
            }
            TreeListViewItem item = this[index];
            if (this[index].Visible && this.TreeListView != null)
            {
                item.Hide();
            }
            List.RemoveAt(index);
            item.SetParent(null);
            // Redraw parent if no more children
            if (Count == 0 && TreeListView != null && Parent != null)
            {
                Parent.Redraw();
            }
            // Redraw new last item
            if (Count > 0 && TreeListView != null && index == Count)
            {
                this[index - 1].Redraw();
            }
            OnItemRemoved(new TreeListViewEventArgs(item, TreeListViewAction.Unknown));
        }

        private int GetInsertTreeListViewIndex(TreeListViewItem item, int collectionindex)
        {
            if (TreeListView == null) return -1;
            if (TreeListView != null)
            {
                if (TreeListView.InvokeRequired)
                {
                    throw (new Exception("Invoke required"));
                }
            }
            if (Owner != null)
            {
                int a = 0;
                a++;
            }
            int index = -1;
            // First level item (no parent)
            if (Owner != null && collectionindex != -1)
            {
                index = collectionindex == 0 ? 0 : this[collectionindex - 1].LastChildIndexInListView + 1;
            }
            else if (Parent != null && collectionindex != -1)
            {
                if (!Parent.Visible || !Parent.IsExpanded) index = -1;
                else
                {
                    index = collectionindex == 0 ? Parent.Index + 1 : Parent.Items[collectionindex - 1].LastChildIndexInListView + 1;
                }
            }
            return index;
        }

        private int GetInsertCollectionIndex(TreeListViewItem item)
        {
            if (TreeListView != null)
            {
                if (TreeListView.InvokeRequired)
                {
                    throw (new Exception("Invoke required"));
                }
            }
            int index = -1;
            if (!_Sortable) index = Count;
            else if (!Contains(item) && !ListViewContains(item))
            {
                switch (SortOrder)
                {
                    // No sortorder -> at the end of the collection
                    case System.Windows.Forms.SortOrder.None:
                        index = this.Count;
                        break;
                    default:
                        for (int i = 0; i < this.Count; i++)
                        {
                            // Change the index for the compare if the order is descending
                            int indexcompare = i;
                            int comp = Comparer.Compare(item, this[indexcompare]);
                            if (comp <= 0)
                            {
                                index = indexcompare;
                                break;
                            }
                        }
                        index = index == -1 ? this.Count : index;
                        break;
                }
            }
            return index;
        }

        /// <summary>
        /// Gets or sets a value indicating whether the items of the collection can be reorder while the sort function is being called
        /// </summary>
        public bool Sortable
        {
            get { return _Sortable; }
            set { _Sortable = value; }
        }

        /// <summary>
        /// Get or set the new sortorder (apply automatically the sort function
        /// if the sortorder value is changed)
        /// </summary>
        public SortOrder SortOrder
        {
            get { return (Comparer.SortOrder); }
            set
            {
                Comparer.SortOrder = value;
                Sort(false);
            }
        }

        /// <summary>
        /// Gets the comparer used in the Sort and Add functions
        /// </summary>
        public ITreeListViewItemComparer Comparer
        {
            get { return _Comparer; }
            set { _Comparer = value; }
        }

        /// <summary>
        /// Set the new sortorder (apply automatically the sort function
        /// if the sortorder value is changed) for each collection recursively
        /// </summary>
        public SortOrder SortOrderRecursively
        {
            set
            {
                if (TreeListView != null)
                {
                    if (TreeListView.InvokeRequired)
                    {
                        TreeListView.Invoke(new VoidHandlerSortOrder(SetSortOrderRecursively), new object[] { value });
                        return;
                    }
                }
                SetSortOrderRecursively(value);
            }
        }

        private void SetSortOrderRecursively(SortOrder value)
        {
            SortOrder = value;
            foreach (TreeListViewItem item in this)
            {
                item.Items.SortOrderRecursively = value;
            }
        }

        internal SortOrder SortOrderRecursivelyWithoutSort
        {
            set
            {
                if (TreeListView != null)
                {
                    if (TreeListView.InvokeRequired)
                    {
                        throw (new Exception("Invoke Required"));
                    }
                }
                Comparer.SortOrder = value;
                foreach (TreeListViewItem item in this)
                {
                    item.Items.SortOrderRecursivelyWithoutSort = value;
                }
            }
        }

        /// <summary>
        /// TreeListView control that directly contains this collection
        /// </summary>
        public TreeListView Owner
        {
            get { return _Owner; }
        }

        /// <summary>
        /// TreeListViewItem that contains this collection
        /// </summary>
        public TreeListViewItem Parent
        {
            get { return _Parent; }
        }

        /// <summary>
        /// Returns the TreeListView set in Owner or in Parent
        /// </summary>
        private TreeListView TreeListView
        {
            get
            {
                if (Owner != null) return Owner;
                if (Parent != null) return Parent.ListView;
                return (null);
            }
        }

        /// <summary>
        /// Get an item in the collection
        /// </summary>
        public virtual TreeListViewItem this[int index]
        {
            get
            {
                return ((TreeListViewItem)this.List[index]);
            }
        }


        public class TreeListViewItemCollectionComparer : ITreeListViewItemComparer
        {
            private SortOrder _SortOrder = SortOrder.Ascending;
            private int _Column;

            public TreeListViewItemCollectionComparer()
                : this(SortOrder.Ascending, 0)
            {
            }

            public TreeListViewItemCollectionComparer(SortOrder order)
                : this(order, 0)
            {
                SortOrder = order;
            }

            public TreeListViewItemCollectionComparer(SortOrder order, int column)
            {
                SortOrder = order;
                _Column = column;
            }

            public SortOrder SortOrder
            {
                get { return (_SortOrder); }
                set { _SortOrder = value; }
            }

            public int Column
            {
                get { return (_Column); }
                set { _Column = value; }
            }

            public int Compare(object x, object y)
            {
                TreeListViewItem a = (TreeListViewItem)x;
                TreeListViewItem b = (TreeListViewItem)y;
                int result = 1;
                if (Column < a.SubItems.Count && Column < b.SubItems.Count)
                {
                    result = string.CompareOrdinal(a.SubItems[Column].Text.ToUpper(), b.SubItems[Column].Text.ToUpper());
                }
                switch (SortOrder)
                {
                    case SortOrder.Ascending:
                        return result;
                    case SortOrder.Descending:
                        return (-result);
                    default:
                        return 1;
                }
            }
        }
    }
}