// BookmarkList.cs
//
//  Copyright (C) 2009 Christian Eide
//
// 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 2 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, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//

using System;
using Gtk;
using bareFTP.Preferences.Bookmarks;

namespace bareFTP.Gui.Preferences
{
	
	
	public class BookmarkList : TreeView
	{
		private TreePath clickedPath; 
		private BookmarkStore store;
		public event EventHandler ItemDeleted;
		
		public BookmarkList()
		{
			this.ShowExpanders = true;
			this.HeadersVisible = false;
			this.Selection.Mode = SelectionMode.Single;
			this.Reorderable = false;
			
			Gtk.TargetEntry[] te1 = new TargetEntry[] { new TargetEntry("bookmark", Gtk.TargetFlags.Widget, 0)};
			EnableModelDragSource(Gdk.ModifierType.Button1Mask, te1, Gdk.DragAction.Move);
			EnableModelDragDest(te1, Gdk.DragAction.Move);
			
			store = new BookmarkStore(typeof(BookmarkItem));
			TreeViewColumn bookmarkColumn = new TreeViewColumn ();
			MyCellRendererPixbuf iconCell = new MyCellRendererPixbuf();
			MyCellRendererText nameCell = new MyCellRendererText(170);
			bookmarkColumn.PackStart(iconCell, false);
			bookmarkColumn.PackStart(nameCell, false);
			bookmarkColumn.SetCellDataFunc (nameCell, new Gtk.TreeCellDataFunc (OnBookmarkData));
			this.AppendColumn(bookmarkColumn);
			this.Model = store;
			this.Selection.Mode = Gtk.SelectionMode.Single;
			
		}

		void OnBookmarkData (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter)
		{
			
			BookmarkItem item = (BookmarkItem)store.GetValue(iter, 0);
			(cell as MyCellRendererText).Text = item.Name;
			
			foreach(Gtk.CellRenderer c in tree_column.CellRenderers)
			{
				if(c is MyCellRendererPixbuf)
				{
					MyCellRendererPixbuf iconcell = (MyCellRendererPixbuf)c;
					if(item is BookmarkEntry)
					{
						iconcell.Pixbuf = Gtk.IconTheme.Default.LoadIcon(Gtk.Stock.File, 16, 0);
					}
					else if(item is BookmarkFolder)
					{
						iconcell.Pixbuf = Gtk.IconTheme.Default.LoadIcon(Gtk.Stock.Directory, 16, 0);
					}
				}
			}
			
			
		}

		
		protected override bool OnButtonPressEvent (Gdk.EventButton evnt)
		{
			if(evnt.Button == 1)
			{
				TreePath currentPath;
				if (GetPathAtPos((int) evnt.X, (int) evnt.Y, out currentPath))
				{
					clickedPath = currentPath;
				}				
			}
			else if(evnt.Button == 3)
			{
            	ShowPopup();
				return false;
			}
			return base.OnButtonPressEvent(evnt);
		}
		
		protected override bool OnDragDrop (Gdk.DragContext context, int x, int y, uint time_)
		{
			
			if ( clickedPath != null )
			{
				// find the destination (drop) row for this (x,y) coord
				TreePath tp;
				TreeIter srciter;
				TreeIter dstiter;
				TreeViewDropPosition pos;
				
				store.GetIter(out srciter, clickedPath);
				
				bool foundRow = GetDestRowAtPos (x, y, out tp, out pos);
				
				
				if(foundRow)
				{
					store.GetIter(out dstiter, tp);
					BookmarkItem item = (BookmarkItem)store.GetValue(dstiter, 0);
					
					if(item is BookmarkEntry)
					{
						if (pos == TreeViewDropPosition.Before || pos == TreeViewDropPosition.IntoOrBefore)
							store.MoveBefore(srciter, dstiter);
						else
							store.MoveAfter(srciter, dstiter);
					}
					else
					{
						if (pos == TreeViewDropPosition.IntoOrAfter || pos == TreeViewDropPosition.IntoOrBefore)
							store.MoveInto(srciter, dstiter);
						else if(pos == TreeViewDropPosition.After)
							store.MoveAfter(srciter, dstiter);
						else
							store.MoveBefore(srciter, dstiter);
					}
				}
				else
					store.MoveBottom(srciter);
			}
			
			Gtk.Drag.Finish (context, true, false, time_);
			return true;
		}
		
		protected override bool OnDragMotion (Gdk.DragContext context, int x, int y, uint time_)
		{
			if (!base.OnDragMotion (context, x, y, time_))
				return false;
			
			TreePath path;
			TreeIter srciter;
			TreeIter iter;
			
			if (GetPathAtPos(x, y, out path))
			{
				store.GetIter(out srciter, clickedPath);
				store.GetIter(out iter, path);
				if(store.IsAncestor(srciter, iter))
				{
					SetDragDestRow(null, 0);
					return false;
				}
			}
			
			TreeViewDropPosition pos;
			store.GetIter(out srciter, clickedPath);
			
			
			if (GetDestRowAtPos(x, y, out path, out pos))
			{
				Model.GetIter(out iter, path);
				BookmarkItem item = (BookmarkItem)Model.GetValue(iter, 0);
				
				if(item is BookmarkEntry)
				{
					SetDragDestRow(path, (TreeViewDropPosition)((int)pos & 0x1));
				}
			}
			
			return true;
		}
		
		protected override void OnDragEnd (Gdk.DragContext context)
		{
			Model = store;
		}

		private void ShowPopup ()
    	{
			using(Gtk.Menu menu = new Gtk.Menu())
			{
				Gtk.ImageMenuItem m_newbookmark = new Gtk.ImageMenuItem(Mono.Unix.Catalog.GetString("New bookmark"));
				m_newbookmark.Name = "m_newbookmark";
				m_newbookmark.Image = new Gtk.Image(Gtk.IconTheme.Default.LoadIcon(Gtk.Stock.New, 16, 0));
				m_newbookmark.Activated += OnNewBookmark;
				menu.Append(m_newbookmark);
				
				Gtk.ImageMenuItem m_newfolder = new Gtk.ImageMenuItem(Mono.Unix.Catalog.GetString("New folder"));
				if(Gtk.IconTheme.Default.HasIcon("stock_new-dir"))
					m_newfolder.Image = new Gtk.Image(Gtk.IconTheme.Default.LoadIcon("stock_new-dir", 16, 0));
				else
					m_newfolder.Image = new Gtk.Image(Gtk.IconTheme.Default.LoadIcon(Gtk.Stock.Directory, 16, 0));
				
				m_newfolder.Activated += OnNewBookmark;
				menu.Append(m_newfolder);
				
				Gtk.ImageMenuItem m_delete = new Gtk.ImageMenuItem(Mono.Unix.Catalog.GetString("Delete"));
				m_delete.Image = new Gtk.Image(Gtk.IconTheme.Default.LoadIcon(Gtk.Stock.Delete, 16, 0));
				m_delete.Activated += delegate {
					if(Selection.CountSelectedRows() > 0)
					{
						Gtk.TreeIter iter;
						Selection.GetSelected(out iter);
						BookmarkItem item = (BookmarkItem)store.GetValue(iter, 0);
						
						if(bareFTP.Gui.Dialog.Dialogs.QuestionDialog(string.Format(Mono.Unix.Catalog.GetString("Are you sure you want to delete {0}?"), item.Name)))
						{
							store.Remove(ref iter);
							ItemDeleted(null,null);
						}
					}
					
				};
				menu.Append(m_delete);

				menu.Popup();
				menu.ShowAll();
			}
		}

		private void OnNewBookmark(object sender, EventArgs e)
		{
			Gtk.TreeIter iter;
			BookmarkItem newitem;
			Gtk.ImageMenuItem m = sender as Gtk.ImageMenuItem;
			if(m.Name == "m_newbookmark")
				newitem = new BookmarkEntry(Mono.Unix.Catalog.GetString("New bookmark"));
			else
				newitem = new BookmarkFolder(Mono.Unix.Catalog.GetString("New folder"));
			
			if(Selection.CountSelectedRows() == 1)
			{
				Selection.GetSelected(out iter);
				BookmarkItem item = (BookmarkItem)store.GetValue(iter, 0);
				if(item is BookmarkFolder)
				{
					Gtk.TreePath path = store.GetPath(iter);
					iter = store.AppendValues(iter, newitem);
					ExpandRow(path, false);
				}
				else
				{
					Gtk.TreeIter piter;
					if(Model.IterParent(out piter, iter))
					{
						iter = store.AppendValues(piter, newitem);
					}
					else
						iter = store.AppendValues(newitem);
				}
			}
			else
				iter = store.AppendValues(newitem);
			
			Selection.SelectIter(iter);
		}

	}
}
