﻿using System.Collections;
using System.Collections.Generic;

namespace Fugu.Excel
{
    public abstract class ExcelCollection<TItem> : IEnumerable<TItem>, IEnumerable
    {
        private object _lockItems = new object();

        protected IList<TItem> _items;

        protected ExcelCollection()
        {
            _items = new List<TItem>();
        }

        public virtual TItem this[int index]
        {
            get
            {
                Contract.Requires(index >= 0, nameof(index));

                if (_items.Count <= index)
                {
                    lock (_lockItems)
                    {
                        if (_items.Count <= index)
                        {
                            AddNewItems(index - _items.Count + 1);
                        }
                    }
                }

                return _items[index];
            }
        }

        public virtual int Count
        {
            get
            {
                return _items.Count;
            }
        }

        public virtual void Clear()
        {
            lock (_lockItems)
            {
                for (int index = _items.Count - 1; index >= 0; --index)
                {
                    TItem obj = _items[index];
                    HandleItemRemoving(obj);
                    _items.RemoveAt(index);
                    HandleItemRemoved(obj);
                }
            }
        }

        protected void AddNewItems(int count)
        {
            int count1 = _items.Count;

            for (int index = 0; index < count; ++index)
            {
                TItem obj = CreateItem(count1++);
                HandleItemAdding(obj);
                _items.Add(obj);
                HandleItemAdded(obj);
            }
        }

        protected abstract TItem CreateItem(int index);

        protected virtual void HandleItemAdding(TItem item)
        {
        }

        protected virtual void HandleItemAdded(TItem item)
        {
        }

        protected virtual void HandleItemRemoving(TItem item)
        {
        }

        protected virtual void HandleItemRemoved(TItem item)
        {
        }

        public virtual IEnumerator<TItem> GetEnumerator()
        {
            return _items.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}