context: using System;
  using Gtk;
  using Gnome;
  using System.Collections;
  using Mono.Unix;
  
  namespace FSpot {
  	public class TimeChangedEventArgs : DbItemEventArgs {
  		TimeSpan span;
  
  		public TimeChangedEventArgs (DbItem [] items, TimeSpan span) : base (items)
  		{
  			this.span = span;
  		}
  
  		public TimeSpan TimeSpan {
  			get {
  				return span;
  			}
  		}
  	}
  
  	public class TimeDialog : GladeDialog 
  	{
  		[Glade.Widget] ScrolledWindow view_scrolled;
  		[Glade.Widget] ScrolledWindow tray_scrolled;
  
  		//[Glade.Widget] Button back_button;
  		//[Glade.Widget] Button forward_button;
  		[Glade.Widget] Button ok_button;
  		[Glade.Widget] Button cancel_button;
  
  		[Glade.Widget] SpinButton photo_spin;
  
  		[Glade.Widget] Label name_label;
  		[Glade.Widget] Label old_label;
  		[Glade.Widget] Label count_label;
  
  		[Glade.Widget] DateEdit date_edit;
  
  		[Glade.Widget] Frame tray_frame;
  		
  		[Glade.Widget] Gtk.Entry entry;
  		[Glade.Widget] Gtk.Entry offset_entry;
  		
  		[Glade.Widget] Gtk.CheckButton difference_check;
  		[Glade.Widget] Gtk.CheckButton interval_check;
  		[Glade.Widget] Gtk.Frame action_frame;
  		[Glade.Widget] Gtk.Entry spacing_entry;
  		[Glade.Widget] Gtk.Label starting_label;
  		
  		IBrowsableCollection collection;
  		BrowsablePointer Item;
  		IconView tray;
  		PhotoImageView view;
  		Db db;
  		TimeSpan gnome_dateedit_sucks;
  
  		public TimeDialog (Db db, IBrowsableCollection collection) : base ("time_dialog")
  		{
  			this.db = db;
  			this.collection = collection;
  
  			tray = new TrayView (collection);
  			tray_scrolled.Add (tray);
  			tray.Selection.Changed += HandleSelectionChanged;
  
  			view = new PhotoImageView (collection);
  			view_scrolled.Add (view);
  			Item = view.Item;
  			Item.Changed += HandleItemChanged;
  			Item.MoveFirst ();
  
  			//forward_button.Clicked += HandleForwardClicked;
  			//back_button.Clicked += HandleBackClicked;
  			ok_button.Clicked += HandleOkClicked;
  			cancel_button.Clicked += HandleCancelClicked;
  
  			photo_spin.ValueChanged += HandleSpinChanged;
  			photo_spin.SetIncrements (1.0, 1.0);
  			photo_spin.Adjustment.StepIncrement = 1.0;
  			photo_spin.Wrap = true;
  
  			date_edit.TimeChanged += HandleTimeChanged;
  			date_edit.DateChanged += HandleTimeChanged;
  			Gtk.Entry entry = (Gtk.Entry) date_edit.Children [0];
  			entry.Changed += HandleTimeChanged;
  			entry = (Gtk.Entry) date_edit.Children [2];
  			entry.Changed += HandleTimeChanged;
  			offset_entry.Changed += HandleOffsetChanged;
  			Dialog.ShowAll ();
  			HandleCollectionChanged (collection);
  
  			spacing_entry.Changed += HandleSpacingChanged;
  			spacing_entry.Sensitive = ! difference_check.Active;
  		      
  			difference_check.Toggled += HandleActionToggled;
  		}
  
  		DateTime EditTime {
  			get { return date_edit.Time - gnome_dateedit_sucks; }
  		}
  
  		TimeSpan Offset
  		{
  			get {
  				System.Console.WriteLine ("{0} - {1} = {2}", date_edit.Time, Item.Current.Time, date_edit.Time - Item.Current.Time);
  				return EditTime - Item.Current.Time;
  			}
  			set {
  				date_edit.Time = Item.Current.Time - gnome_dateedit_sucks + value;
  			}
  		}
  
  		void HandleTimeChanged (object sender, EventArgs args)
  		{
  			TimeSpan span = Offset;
  			System.Console.WriteLine ("time changed {0}", span);
  			if (! offset_entry.HasFocus)
  				offset_entry.Text = span.ToString ();
  
  			// The preceding text here is the second checkbutton in the Time dialog
  			// that says "Space all photos by []"
  #if false
  			starting_label.Text = String.Format (Catalog.GetString ("min. Starting at {0}"),
  							     EditTime);
  #else
  			starting_label.Text = "min.";
  #endif
  			difference_check.Label = String.Format (Catalog.GetString ("Shift all photos by {0}"),
  							      Offset);
  		}
  
  		void HandleItemChanged (BrowsablePointer pointer, BrowsablePointerChangedArgs args)
  		{
  			//back_button.Sensitive = (Item.Index > 0 && collection.Count > 0);
  			//forward_button.Sensitive = (Item.Index < collection.Count - 1);
  
  			if (Item.IsValid) {
  				IBrowsableItem item = Item.Current;
  				
  				name_label.Text = item.Name;;
  				old_label.Text = item.Time.ToLocalTime ().ToString ();
  				
  				int i = collection.Count > 0 ? Item.Index + 1: 0;
  				// This indicates the current photo is photo {0} of {1} out of photos
  				count_label.Text = System.String.Format (Catalog.GetString ("{0} of {1}"), i, collection.Count);
  
  				DateTime actual = item.Time;
  				date_edit.Time = actual;
  				gnome_dateedit_sucks = date_edit.Time - actual;
  			}
  			HandleTimeChanged (this, System.EventArgs.Empty);
  
  			if (!tray.Selection.Contains (Item.Index)) {
  				tray.Selection.Clear ();
  				tray.Selection.Add (Item.Index);
  			}
  
  			photo_spin.Value = Item.Index + 1;
  		}
  
  		private void ShiftByDifference ()
  		{
  			TimeSpan span = Offset;
  			Photo [] photos = new Photo [collection.Count];
  
  			for (int i = 0; i < collection.Count; i++) {
  				Photo p = (Photo) collection [i];
  				DateTime time = p.Time;
  				p.Time = time + span;
  				photos [i] = p;
  				System.Console.WriteLine ("XXXXX old: {0} new: {1} span: {2}", time, p.Time, span);
  			}
  			
  			db.Photos.Commit (photos, new TimeChangedEventArgs (photos, span));
  		}
  
  		private void SpaceByInterval ()
  		{
  			DateTime date = EditTime;
  		        long ticks = (long) (double.Parse (spacing_entry.Text) * TimeSpan.TicksPerMinute);
  			TimeSpan span = new TimeSpan (ticks);
  			Photo [] photos = new Photo [collection.Count];
  			
  			for (int i = 0; i < collection.Count; i++) {
  				photos [i] = (Photo) collection [i];
  			}
  			
  			TimeSpan accum = new TimeSpan (0);
  			for (int j = Item.Index; j > 0; j--) {
  				date -= span;
  			}
  
  			for (int i = 0; i < photos.Length; i++) {
  				photos [i].Time = date + accum;
  				accum += span;
  			}
  			
  			db.Photos.Commit (photos, new TimeChangedEventArgs (photos, span));
  		}
  
  		void HandleSpinChanged (object sender, EventArgs args)
  		{
  			Item.Index = photo_spin.ValueAsInt - 1;
  		}
  
  		void HandleOkClicked (object sender, EventArgs args)
  		{
  			if (! Item.IsValid)
  				throw new ApplicationException ("invalid item selected");
  
  			Dialog.Sensitive = false;
  			
  			if (difference_check.Active)
  				ShiftByDifference ();
  			else
  				SpaceByInterval ();
  
  
  			Dialog.Destroy ();
  		}
  
  		void HandleOffsetChanged (object sender, EventArgs args)
  		{
  			System.Console.WriteLine ("offset = {0}", Offset);
  			TimeSpan current = Offset;
  			try {
  
gt: 				TimeSpan span = TimeSpan.Parse (offset_entry.Text);