using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using Xamarin.Forms;
using Aurora.Proto.Party;

namespace Aurora.Design.Components.MemberList
{
    public partial class MemberList : ContentView
    {
        private static ObservableCollection<PartyMember> _newSource;
        // private static NotifyCollectionChangedEventHandler _collectionChangedHandler;
        public MemberList()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Bindable property for members list.
        /// </summary>
        /// <param name=""Members""></param>
        /// <param name="typeof(IEnumerable<string>"></param>
        /// <returns></returns>
        public static readonly BindableProperty MembersProperty =
            BindableProperty.Create(propertyName: "Members",
            returnType: typeof(ObservableCollection<PartyMember>),
            declaringType: typeof(MemberList),
            defaultBindingMode: BindingMode.Default,
            propertyChanged: OnMembersChanged);

        /// <summary>
        /// Backing property for MembersProperty
        /// </summary>
        /// <value></value>
        public ObservableCollection<PartyMember> Members
        {
            get
            {
                return (ObservableCollection<PartyMember>)GetValue(MembersProperty);
            }
            set
            {
                SetValue(MembersProperty, value);
            }
        }


        /// <summary>
        /// Memberes changed event handler. Assign member list source.
        /// </summary>
        /// <param name="bindable"></param>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        private static void OnMembersChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var control = (MemberList)bindable;
            var membersList = control.FindByName("MembersHorizontalList") as HorizontalList.HorizontalList;
            if (membersList != null)
            {
                _newSource = newValue as ObservableCollection<PartyMember>;
                membersList.ItemsSource = new ObservableCollection<object>(_newSource);

                //Setup collection changed listeners
                //TODO evaluate for memory leak
                _newSource.CollectionChanged += (sender, e) => HandleCollectionChanged(sender, e, bindable);
            }
        }

        private static void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, BindableObject bindable)
        {
            MemberList self = bindable as MemberList;
            var membersList = self.FindByName("MembersHorizontalList") as HorizontalList.HorizontalList;

            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    {
                        foreach (PartyMember member in e.NewItems)
                        {
                            membersList.ItemsSource.Add(member);
                        }

                        break;
                    }
                case NotifyCollectionChangedAction.Remove:
                    {
                        foreach (PartyMember member in e.NewItems)
                        {
                            //Find all matches
                            var sourceMembers = membersList.ItemsSource.Where((object obj) =>
                            {
                                bool match = false;
                                if (obj is PartyMember)
                                {
                                    PartyMember tmp = obj as PartyMember;
                                    match = tmp.Id == member.Id;
                                }

                                return match;
                            });

                            //Remove found matches
                            foreach (object obj in sourceMembers)
                            {
                                membersList.ItemsSource.Remove(obj);
                            }
                        }

                        break;
                    }
            }
        }
    }
}