// WideMargin. Simple fast bible software.
// Copyright (C) 2011  Daniel Hughes
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using Gtk;
using System.Linq;
using System.Data.Linq;
using System.Collections.Generic;
using WideMargin.MVCInterfaces;
using System.Text;
using WideMargin.Utilities;

namespace WideMargin.GUI
{
	/// <summary>
	/// Widget for displaying search results
	/// </summary>
	public class SearchResultsWidget : FilteredView, ISearchResultsView
	{
		private EventLocker _eventLocker = new EventLocker();
		private EventHandler<EventArgs> _moreResultsRequried;
		
		/// <summary>
		/// Initializes a new instance of the <see cref="WideMargin.GUI.SearchResultsWidget"/> class.
		/// </summary>
		public SearchResultsWidget()
			:base()
		{
			this.SizeRequested += HandleHandleSizeRequested;
		}
		
		/// <summary>
		/// Occurs when the widget is resized.
		/// It the scrollbars are not visable requests more results
		/// </summary>
		private void HandleHandleSizeRequested (object o, SizeRequestedArgs args)
		{
			if(!VScrollbarVisible)
			{
				_moreResultsRequried.Fire(this, EventArgs.Empty);	
			}
		}
		
		protected override void HandleTextViewScrollbarAtBottom (object sender, EventArgs e)
		{
			base.HandleTextViewScrollbarAtBottom (sender, e);
			_moreResultsRequried.Fire(sender, EventArgs.Empty);
		}
		
		/// <summary>
		/// Clears out all the displayed results
		/// </summary>
		public void Clear()
		{
			this.Invoke(() =>
			{
				ClearText();
			});
		}

		public void SetResults(IEnumerable<IVerse> verses, IEnumerable<Filter> filters)
		{
			this.Invoke(() =>
			{
				ClearText();
				AppendResultsUnsafe(verses);
				SetFiltersUnsafe(filters);
			});
		}

		private void AppendResultsUnsafe (IEnumerable<IVerse> verses)
		{
			StringBuilder builder = new StringBuilder();
				
			builder.Append("<Text>");
				
			foreach(var verse in verses)
			{
				builder.AppendFormat(" <VerseLink target='{0}'>{1}</VerseLink> {2}",
					                 verse.Identifier,
					                 verse.Identifier,
					                 Environment.NewLine);
				builder.AppendLine(verse.Contents);
				builder.AppendLine ();
			}
				
			builder.Append("</Text>");
			AppendText(builder.ToString());
		}

		/// <summary>
		/// Appends the results to the end of the view
		/// </summary>
		/// <param name='verses'>Verses to append</param>
		public void AppendResults(IEnumerable<IVerse> verses)
		{
			this.Invoke(() =>
          	{
				AppendResultsUnsafe(verses);
			});
		}
		
		/// <summary>
		/// Occurs when the view requires more search results
		/// </summary>
		public event EventHandler<EventArgs> MoreResultsRequired
		{
			add
			{
				_eventLocker.Add(ref _moreResultsRequried, value);
			}
			remove
			{
				_eventLocker.Remove(ref _moreResultsRequried, value);
			}
		}
	}
}

