using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation.Collections;

namespace ReflectionIT.Windows8.Helpers {

    public class BindableObservableCollection<T> : ObservableCollection<T>, IObservableVector<object> {
        public event VectorChangedEventHandler<object> VectorChanged;

        public BindableObservableCollection() : base() {

        }

        public BindableObservableCollection(IEnumerable<T> collection)
            : base(collection) {

        }

        public int IndexOf(object item) {
            return base.IndexOf((T)item);
        }

        public void Insert(int index, object item) {
            base.Insert(index, (T)item);
            RaiseChange(CollectionChange.ItemInserted, (uint)index);
        }

        private void RaiseChange(CollectionChange type, uint index) {
            if (VectorChanged != null)
                VectorChanged(this, new VectorChangedEventArgs(type, index));
        }

        public new object this[int index] {
            get {
                return (object)base[index];
            }
            set {
                base[index] = (T)value;
                RaiseChange(CollectionChange.ItemChanged, (uint)index);
            }
        }

        public void Add(object item) {
            base.Add((T)item);
            RaiseChange(CollectionChange.ItemInserted, (uint)(base.Count - 1));
        }

        protected override void ClearItems() {
            base.ClearItems();
            RaiseChange(CollectionChange.Reset, 0);
        }

        public bool Contains(object item) {
            return base.Contains((T)item);
        }

        public void CopyTo(object[] array, int arrayIndex) {
            throw new NotImplementedException();
        }

        public bool IsReadOnly {
            get { throw new NotImplementedException(); }
        }

        public bool Remove(object item) {
            int index = base.IndexOf((T)item);
            if (index >= 0) {
                var res = base.Remove((T)item);
                RaiseChange(CollectionChange.ItemRemoved, (uint)index);
                return res;
            }

            return false;
        }

        private VectorEnumerator<T> _Enum;
        public new IEnumerator<object> GetEnumerator() {
            if (_Enum == null) {
                _Enum = new VectorEnumerator<T>(this);
            }

            return _Enum;
        }
    }

    public class VectorChangedEventArgs : IVectorChangedEventArgs {
        public VectorChangedEventArgs(CollectionChange type, uint index) {
            CollectionChange = type;
            Index = index;
        }
        public CollectionChange CollectionChange { get; set; }
        public uint Index { get; set; }
    }

    public class VectorEnumerator<T> : IEnumerator<object> {
        private IEnumerable<T> _Coll;
        private IEnumerator<T> _Enum;

        public VectorEnumerator(IEnumerable<T> internalColl) {
            _Coll = internalColl;
            _Enum = _Coll.GetEnumerator();
        }

        public object Current {
            get { return (object)_Enum.Current; }
        }


        public bool MoveNext() {
            return _Enum.MoveNext();
        }

        public void Reset() {
            _Enum.Reset();
        }

        public void Dispose() {
            _Enum.Dispose();
        }
    }

}
