using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using BeWo.ServiceProxy;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;

namespace BeWo.View.Search
{
	public class GenericSearchView<T> : UserControl
		where T : class, IFilterableDC
	{
		private readonly Grid _ContentGrid;

		private readonly Grid _HeaderGrid;

		private readonly ListBox _ResultListBox;

		private readonly Grid _Root;

		private readonly TextBox _Searchbox;

		internal List<T> _ObjectList;

		private bool mAutoGetAllAfterLoaded = true;

		public GenericSearchView()
		{
			SearchMode = SearchMode.All;

			if (!DesignerProperties.GetIsInDesignMode(this))
			{
				Loaded += GenericSearchView_Loaded;
			}

			_Root = new Grid {Background = Brushes.Black};
			_Root.RowDefinitions.Add(new RowDefinition {Height = GridLength.Auto});
			_Root.RowDefinitions.Add(new RowDefinition {Height = new GridLength(1, GridUnitType.Star)});

			_HeaderGrid = new Grid {Margin = new Thickness(5, 5, 5, 3)};
			_HeaderGrid.ColumnDefinitions.Add(new ColumnDefinition {Width = GridLength.Auto});
			_HeaderGrid.ColumnDefinitions.Add(new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)});

			_HeaderGrid.Children.Add(new Label {Content = "Suche:", Foreground = Brushes.White, FontSize = 14d});

			_Searchbox = new TextBox {Margin = new Thickness(3), TabIndex = 0, Height = 23, BorderThickness = new Thickness(0), HorizontalAlignment = HorizontalAlignment.Stretch};

			if (!DesignerProperties.GetIsInDesignMode(this))
			{
				_Searchbox.Template = FindResource("SearchTextBoxTemplate") as ControlTemplate;
			}

			Grid.SetColumn(_Searchbox, 1);
			_HeaderGrid.Children.Add(_Searchbox);
			_Root.Children.Add(_HeaderGrid);

			_ContentGrid = new Grid();
			_ContentGrid.RowDefinitions.Add(new RowDefinition {Height = GridLength.Auto});
			_ContentGrid.RowDefinitions.Add(new RowDefinition {Height = new GridLength(1, GridUnitType.Star)});

			_ContentGrid.ColumnDefinitions.Add(new ColumnDefinition {Width = GridLength.Auto});
			_ContentGrid.ColumnDefinitions.Add(new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)});

			_ContentGrid.Margin = new Thickness(5, 0, 5, 5);

			Grid.SetRow(_ContentGrid, 1);
			Grid.SetColumnSpan(_ContentGrid, 2);

			_Root.Children.Add(_ContentGrid);

			_ResultListBox = new ListBox {MinWidth = 200, MinHeight = 200, Background = null};

			if (!DesignerProperties.GetIsInDesignMode(this))
			{
				_ResultListBox.Style = FindResource("NavigationListStyle") as Style;
			}
            
			Grid.SetRow(_ResultListBox, 1);
			Grid.SetColumnSpan(_ResultListBox, 2);

			_ContentGrid.Children.Add(_ResultListBox);

			Content = _Root;

			_Searchbox.Loaded += (s, e) =>
			{
				//this._Searchbox.Text = string.Empty;
				_Searchbox.SelectAll();
				_Searchbox.Focus();
			};
			_Searchbox.TextChanged += (s, e) => { UpdateFilteredList(); };
			_Searchbox.PreviewKeyDown += (s, e) =>
			{
				if (e.Key == Key.Enter)
				{
					OpenSelectedObject();
				}
				else if (e.Key == Key.Down)
				{
					_ResultListBox.Focus();
				}
			};

			// _ResultListBox.MouseDoubleClick += (s, e) =>
			// {
			// if (_ResultListBox.SelectedItem != null && ItemSelected != null)
			// ItemSelected(this, new EventArgs<T>((T)_ResultListBox.SelectedItem));
			// };
			_ResultListBox.PreviewMouseLeftButtonDown += (s, e) =>
			{
				if (ItemSelected != null)
				{
					Point p = e.GetPosition(_ResultListBox);
					IInputElement elm = _ResultListBox.InputHitTest(p);
					if (elm != null)
					{
						var frwElm = elm as FrameworkElement;
						if (frwElm != null)
						{
							var item = frwElm.TemplatedParent as ListBoxItem;
							if (item != null && item.HasContent)
							{
								var selectedObject = item.Content as T;
								if (selectedObject != null)
								{
									ItemSelected(this, new EventArgs<T>(selectedObject));
								}
							}
						}
					}
				}
			};

			_ResultListBox.PreviewKeyDown += (s, e) =>
			{
				if (e.Key == Key.Enter)
				{
					OpenSelectedObject();
				}
			};

			if (!DesignerProperties.GetIsInDesignMode(this))
			{
				ListItemStyle = FindResource("SearchSimpleStyle") as Style;

                if (typeof(T) == typeof(TextbausteinDC))
                    ListItemStyle = FindResource("NavigationListStyleWithSampleDescAsToolTip") as Style;
			}
		}

		public List<T> ObjectList
		{
			get { return _ObjectList; }
			set { UpdateObjectList(value); }
		}

		public ListBox ResultListBox
		{
			get { return _ResultListBox; }
		}

		public virtual bool AutoGetAllAfterLoaded
		{
			get { return mAutoGetAllAfterLoaded; }
			set { mAutoGetAllAfterLoaded = value; }
		}

		public string SearchText
		{
			get { return _Searchbox.Text; }
			set { _Searchbox.Text = value; }
		}

		public bool IsMultiSelect
		{
			get { return _ResultListBox.SelectionMode == SelectionMode.Extended; }

			set { _ResultListBox.SelectionMode = value ? SelectionMode.Extended : SelectionMode.Single; }
		}

		public Style ListItemStyle
		{
			set { _ResultListBox.ItemContainerStyle = value; }
		}

		public SearchMode SearchMode { get; set; }

		public long? OrganisationRelOid { get; set; }

		public T SelectedItem
		{
			get { return _ResultListBox.SelectedItem as T; }
		}

		public List<T> SelectedItems
		{
			get { return _ResultListBox.SelectedItems.Cast<T>().ToList(); }
		}

		public Brush ThemeColor
		{
			set { _ContentGrid.Background = value; }
		}

		private void GenericSearchView_Loaded(object sender, RoutedEventArgs e)
		{
			if (AutoGetAllAfterLoaded)
			{
				if (_ObjectList == null)
				{
					GetAll(
						cb => this.Dispatch(
							delegate { UpdateObjectList(cb); }));
				}
			}
		}

		public event EventHandler<EventArgs<T>> ItemSelected;

		protected virtual void UpdateObjectList(List<T> list)
		{
			_ObjectList = list;
			UpdateFilteredList();
		}

		protected void AddCustomContentHeaderElement(UIElement element)
		{
			if (element != null)
			{
				//Grid.SetColumnSpan(element, 2);
				_ContentGrid.Children.Add(element);
			}
		}

		protected virtual void GetAll(Action<List<T>> pCallBack)
		{
			ServiceFacade.GetAll(pCallBack);
		}

		protected virtual bool ShowDCInList(object dc)
		{
			return true;
		}

		public void UpdateFilteredList()
		{
			List<string> lFilter = _Searchbox.Text.Split(" ");
			if (_ResultListBox == null || _ObjectList == null)
				return;

			if (SearchMode == SearchMode.OnlyToOrganisationRelatedPersons && _ObjectList.GetType() == typeof (List<CompactPersonDC>))
			{
				var RelatedPersons = new List<CompactPersonDC>();
				if (OrganisationRelOid != null)
				{
					var PersonDCList = _ObjectList as List<CompactPersonDC>;
					Dictionary<CompactPersonDC, List<Organisation2PersonDC>> OrganisationRelationsList = PersonDCList.ToDictionary(element => element, element => element.OrganisationRelations);

					foreach (var organisation2PersonDCs in OrganisationRelationsList)
						RelatedPersons.AddRange(from organisation2PersonDC in organisation2PersonDCs.Value where organisation2PersonDC.Organisation.OrganisationOid == OrganisationRelOid select organisation2PersonDCs.Key);
				}

				_ResultListBox.ItemsSource = RelatedPersons;
			}
			else
			{
				_ResultListBox.ItemsSource = _ObjectList.Where(dc => dc.FilterRelevants.ContainsAll(lFilter) && ShowDCInList(dc));
			}
		}

		private void OpenSelectedObject()
		{
			if (ItemSelected != null)
			{
				var selectedObj = _ResultListBox.SelectedItem as T;
				if (selectedObj == null)
				{
					var list = _ResultListBox.ItemsSource as List<T>;
					if (list == null)
					{
						IEnumerator enu = _ResultListBox.ItemsSource.GetEnumerator();
						enu.MoveNext();
						selectedObj = enu.Current as T;
					}
					else
					{
						if (list.Count > 0)
						{
							selectedObj = list[0];
						}
					}
				}

				if (selectedObj != null)
				{
					ItemSelected(this, new EventArgs<T>(selectedObj));
				}
			}
		}
	}
}