using System;
using System.Collections.Generic;
using Gtk;

namespace DMX2
{
	[System.ComponentModel.ToolboxItem(true)]
	public partial class SeqMacroUI : SequenceurUI
	{
		bool fullUpdFlag = true;
		bool updating;
		SequenceurMacro sequenceur; /* pointe sur les données */
		ListStore lsEffets=null;	/* liste des effets */
		//TreeViewColumn nomCol;	/* inutile dans le contexte macro */

		bool effetChange = false;
		public void EffetChange ()
		{
			effetChange = true;
		}

		void RenamePopup (object sender, ContextMenuEventArgs e)
		{
				Menu m = new Menu();
				MenuItem renameItem = new MenuItem("Renommer le Sequenceur");
				renameItem.ButtonPressEvent +=	new ButtonPressEventHandler(OnRenameItemButtonPressed);
				m.Add(renameItem);
				m.ShowAll();
				m.Popup();
		}


		void OnRenameItemButtonPressed (object o, ButtonPressEventArgs args)
		{
			var dlg = new Dialog ("Nouveau Nom ?", GetAncestor(Gtk.Window.GType) as Gtk.Window , DialogFlags.Modal); var entry = new Entry (sequenceur.Name);
			dlg.AddButton (Stock.Ok, ResponseType.Ok).GrabDefault(); dlg.AddButton (Stock.Cancel, ResponseType.Cancel);
			dlg.VBox.Add (entry); dlg.VBox.ShowAll (); 
			entry.ActivatesDefault=true;

			if ((ResponseType)dlg.Run () == ResponseType.Ok) {
				sequenceur.Name = entry.Text;
				titreLabel.Text = sequenceur.Name;
			}
			dlg.Destroy();
		}

#region construction et gestion de la matrice d'affichage
		protected void ConstruitMatrice ()  /* Matrice d'affichage des effets de la macro */ 
		{

			effetsListe.EnableGridLines= TreeViewGridLines.Both;

			var idCol = new Gtk.TreeViewColumn ();
			var idCell = new Gtk.CellRendererText ();
		
			idCol.Title = "Num";
			idCol.PackStart (idCell, true);
			idCol.SetCellDataFunc (idCell, new Gtk.TreeCellDataFunc (RenderMatriceNum));
			effetsListe.AppendColumn (idCol);


			var nomCol = new Gtk.TreeViewColumn ();
			var nomCell = new Gtk.CellRendererText ();
			nomCol.Title = "Nom";
			nomCol.PackStart (nomCell, true);
			nomCol.SetCellDataFunc (nomCell, new Gtk.TreeCellDataFunc (RenderMatriceNom));
			nomCell.Editable = true;
			nomCell.Edited += OnNomCellEdited;
			effetsListe.AppendColumn (nomCol);

			var topCol = new Gtk.TreeViewColumn ();
			var topCell = new Gtk.CellRendererText ();
			topCol.Title = "Top";
			topCol.PackStart (topCell, true);
			topCol.SetCellDataFunc (topCell, new Gtk.TreeCellDataFunc (RenderMatriceTop));
			topCell.Editable = true;
			topCell.Edited += OnTopCellEdited;
			effetsListe.AppendColumn (topCol);

			var circuitsCol = new Gtk.TreeViewColumn ();
			var circuitsCell = new Gtk.CellRendererText ();
			circuitsCol.Title = "Circuits";
			circuitsCol.PackStart (circuitsCell, true);
			circuitsCol.SetCellDataFunc (circuitsCell, new Gtk.TreeCellDataFunc (RenderMatriceCircuits));
			circuitsCell.Editable = true;
			circuitsCell.Edited += OnCircuitsCellEdited;
			effetsListe.AppendColumn (circuitsCol);

			var valeurCol = new Gtk.TreeViewColumn ();
			var valeurCell = new Gtk.CellRendererText ();
			valeurCol.Title = "Valeur";
			valeurCol.PackStart (valeurCell, true);
			valeurCol.SetCellDataFunc (valeurCell, new Gtk.TreeCellDataFunc (RenderMatriceValeur));
			valeurCell.Editable = true;
			valeurCell.Edited += OnValeurCellEdited;
			effetsListe.AppendColumn (valeurCol);

			var tempsCol = new Gtk.TreeViewColumn ();
			var tempsCell = new Gtk.CellRendererText ();
			tempsCol.Title = "Temps";
			tempsCol.PackStart (tempsCell, true);
			tempsCol.SetCellDataFunc (tempsCell, new Gtk.TreeCellDataFunc (RenderMatriceTemps));
			tempsCell.Editable = true;
			tempsCell.Edited += OnTempsCellEdited;
			effetsListe.AppendColumn (tempsCol);

			lsEffets = new Gtk.ListStore(typeof (SequenceurMacro.Ligne)); 
			this.effetsListe.Model = lsEffets;
			UpdListeEffets();
		}

		void RenderMatriceNum (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter)
		{
			if (Conduite.Courante==null) return;
			string num=string.Empty;
			SequenceurMacro.Ligne l =  tree_model.GetValue (iter, 0) as SequenceurMacro.Ligne;
			if( sequenceur.IndexLigneEnCours == sequenceur.Lignes.IndexOf(l) )
				num+= "->";
			if( sequenceur.IndexLigneaSuivre == sequenceur.Lignes.IndexOf(l) )
				num+= "* ";
			(cell as Gtk.CellRendererText).Text = num + (sequenceur.Lignes.IndexOf(l)+1).ToString();
		
		}

		void RenderMatriceNom (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter)
		{
			if (Conduite.Courante==null) return;
			SequenceurMacro.Ligne l =  tree_model.GetValue (iter, 0) as SequenceurMacro.Ligne;
			(cell as Gtk.CellRendererText).Text = l.Nom;
		}

		void RenderMatriceTop (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter)
		{
			if (Conduite.Courante==null) return;
			SequenceurMacro.Ligne l =  tree_model.GetValue (iter, 0) as SequenceurMacro.Ligne;
			if (l.Top< TimeSpan.Zero) (cell as Gtk.CellRendererText).Text = string.Empty;
			else (cell as Gtk.CellRendererText).Text = (l.Top.TotalMilliseconds /100).ToString();
		}

		void RenderMatriceCircuits (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter)
		{
			if (Conduite.Courante==null) return;
			SequenceurMacro.Ligne l =  tree_model.GetValue (iter, 0) as SequenceurMacro.Ligne;
			(cell as Gtk.CellRendererText).Text = l.Circuits;
		}

		void RenderMatriceValeur (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter)
		{
			if (Conduite.Courante==null) return;
			SequenceurMacro.Ligne l =  tree_model.GetValue (iter, 0) as SequenceurMacro.Ligne;
			(cell as Gtk.CellRendererText).Text = (l.Valeur).ToString();

		}

		void RenderMatriceTemps (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter)
		{
			if (Conduite.Courante==null) return;
			SequenceurMacro.Ligne l =  tree_model.GetValue (iter, 0) as SequenceurMacro.Ligne;
			(cell as Gtk.CellRendererText).Text = (l.Temps.TotalMilliseconds /100).ToString();
		}

		void OnNomCellEdited (object o, EditedArgs args)
		{
			Gtk.TreeIter iter;
			lsEffets.GetIter (out iter, new Gtk.TreePath (args.Path));
			SequenceurMacro.Ligne l = lsEffets.GetValue(iter,0) as SequenceurMacro.Ligne;
			l.Nom = args.NewText;
		}

		void OnTopCellEdited (object o, EditedArgs args)
		{
			Gtk.TreeIter iter;
			lsEffets.GetIter (out iter, new Gtk.TreePath (args.Path));
			SequenceurMacro.Ligne l = lsEffets.GetValue (iter, 0) as SequenceurMacro.Ligne;
			if (args.NewText.Length == 0)
				l.Top = TimeSpan.MinValue;
			else {
				int val;
				if(int.TryParse(args.NewText, out val))
					l.Top = TimeSpan.FromMilliseconds(val *100);
			}
		}

		void OnCircuitsCellEdited (object o, EditedArgs args)
		{
			Gtk.TreeIter iter;
			lsEffets.GetIter (out iter, new Gtk.TreePath (args.Path));
			SequenceurMacro.Ligne l = lsEffets.GetValue(iter,0) as SequenceurMacro.Ligne;
			l.Circuits = args.NewText;
		}


		void OnValeurCellEdited (object o, EditedArgs args)
		{
			Gtk.TreeIter iter;
			lsEffets.GetIter (out iter, new Gtk.TreePath (args.Path));
			SequenceurMacro.Ligne l = lsEffets.GetValue(iter,0) as SequenceurMacro.Ligne;
			int val;
			if(int.TryParse(args.NewText,out val))	l.Valeur = val;
		}

		void OnTempsCellEdited (object o, EditedArgs args)
		{
			Gtk.TreeIter iter;
			lsEffets.GetIter (out iter, new Gtk.TreePath (args.Path));
			SequenceurMacro.Ligne l = lsEffets.GetValue (iter, 0) as SequenceurMacro.Ligne;
			if (args.NewText.Length == 0)
				l.Temps = TimeSpan.Zero;
			else {
				int val;
				if(int.TryParse(args.NewText, out val))
					l.Temps = TimeSpan.FromMilliseconds(val *100);
			}
		}


		void UpdListeEffets ()
		{
			lsEffets.Clear();
			foreach (var ligne in sequenceur.Lignes) {
				lsEffets.AppendValues(ligne);
			}
		}

#endregion

		public SeqMacroUI (SequenceurMacro s ) : base (s)
		{
			this.Build ();
			titreLabel.Text = s.Name;
			sequenceur = s;
			ConstruitMatrice ();


			new ContextMenuHelper(seqMasterScale,MasterPopup);
			new ContextMenuHelper(frame1,RenamePopup);
			new ContextMenuHelper(evBBox,CompteurPopup);


		}

		void MasterPopup (object sender, ContextMenuEventArgs e)
		{
			Menu m = Conduite.Courante.EventManager.GetMenu(null,
			    delegate(object o,string eventId){
					sequenceur.BindMasterEvent(eventId);
				}
			);
			m.ShowAll();
			m.Popup();
		}

		void CompteurPopup (object sender, ContextMenuEventArgs e)
		{
			Menu m = new Menu();

			MenuItem item = new MenuItem("Effet Suivant");
			m.Add(item);
			item.Submenu = Conduite.Courante.EventManager.GetMenu(null,
			    delegate(object o,string eventId){
					sequenceur.BindEffetSuivantEvent(eventId);
				}
			);

			item = new MenuItem("Effet Precedent");
			m.Add(item);
			item.Submenu = Conduite.Courante.EventManager.GetMenu(null,
			    delegate(object o,string eventId){
					sequenceur.BindEffetPrecedentEvent(eventId);
				}
			);

			m.ShowAll();
			m.Popup();

		}


		public override void Update (bool full)
		{
			if (fullUpdFlag || full)
				FullUpdate ();
			// UpdateValues ();  inutil dans le contexte
			timeLabel.LabelProp = string.Format (@"{0:0\.0}", sequenceur.TimeStamp.TotalMilliseconds / 100);

			/*if (sequenceur.EffetCourrant.Duree != TimeSpan.Zero)
				pbDuree.Fraction = Math.Min (1.0d, sequenceur.TimeStamp.TotalMilliseconds / sequenceur.EffetCourrant.Duree.TotalMilliseconds);
			else
				pbDuree.Fraction = 0.0d;

			if (sequenceur.EffetCourrant.Transition != TimeSpan.Zero)
				pbDuree.Fraction = Math.Min (1.0d, sequenceur.TimeStamp.TotalMilliseconds / sequenceur.EffetCourrant.Transition.TotalMilliseconds);
			else
				pbDuree.Fraction = 0.0d;*/

			if (effetChange) {
				UpdListeEffets();
				SelectionneEffet (sequenceur.IndexLigneEnCours);
				posLabel.Text = string.Format("n°{0}",sequenceur.IndexLigneEnCours +1 );
			}
			updating = true;
			seqMasterScale.Value = sequenceur.Master;
			updating = false;

		}


		void SelectionneEffet (int index)
		{
			if(index <0 ) return;
			effetsListe.SetCursor( new TreePath( new int[1] {index })   ,null,false);
			effetChange = false;
		}

		protected void OnCircuitsActionActivated (object sender, EventArgs e)
		{
			// récupère la fenètre principale
			Window win = this.GetAncestor(Gtk.Window.GType) as Window;
			var dlg = new SelSeqCircuits (sequenceur.Circuits,win);
			if ((ResponseType)dlg.Run () == ResponseType.Ok) {
					sequenceur.ChangeCircuits(dlg.GetResultList());
			}
			dlg.Destroy();
			fullUpdFlag = true;
		}

		protected void OnCloseActionActivated (object sender, EventArgs e)
		{
			this.Destroy();
		}

		protected void FullUpdate ()
		{
			fullUpdFlag = true;
		

			/*foreach (Circuit c in sequenceur.Circuits) {


			}*/

			posLabel.Text = string.Format("n°{0}",sequenceur.IndexLigneEnCours +1);

			fullUpdFlag=false;
		}

		int IndexEffetSelectionne()
		{
			var sel = effetsListe.Selection.GetSelectedRows();
			if(sel.Length ==0) return -1;
			return effetsListe.Selection.GetSelectedRows()[0].Indices[0];
		}

		protected void OnGoForwardActionActivated (object sender, EventArgs e)
		{
			// Si l'effet courant est selectioné, on passe au suivant, sinon, on passe a celui selectionné.
			/*if(sequenceur.IndexEffetCourrant == IndexEffetSelectionne())
				sequenceur.IndexEffetCourrant++;
			else
				sequenceur.IndexEffetCourrant = IndexEffetSelectionne();*/

			sequenceur.LigneSuivante();

		}

		protected void OnGoBackActionActivated (object sender, EventArgs e)
		{
			if (sequenceur.IndexLigneEnCours > 0) {
				sequenceur.IndexLigneaSuivre = sequenceur.IndexLigneEnCours - 1;
				sequenceur.LigneSuivante ();
			}
		}

		protected void OnMediaPauseActionActivated (object sender, EventArgs e)
		{
			sequenceur.Paused = ! sequenceur.Paused;
		}		

		protected void OnSeqMasterScaleValueChanged (object sender, EventArgs e)
		{
			if (updating)return;
			sequenceur.Master = (int)(seqMasterScale.Value);
		}

		protected void OnBtnAjoutLigneActivated (object sender, EventArgs e)
		{
			int pos=IndexEffetSelectionne() + 1;
			sequenceur.AjoutLigne(pos);
			UpdListeEffets();
			effetsListe.SetCursor( new TreePath( new int[1] {pos })   , effetsListe.Columns[1] ,true);
		}

		protected void OnRemoveLigneActivated (object sender, EventArgs e)
		{
			int pos = IndexEffetSelectionne();
			if (pos==-1) return;
			sequenceur.RetireLigne(pos);
			UpdListeEffets();
		}		

		protected void OnEffetsListeCursorChanged (object sender, EventArgs e)
		{
			if(effetChange) return;
			TreeViewColumn col;
			TreePath path;
			effetsListe.GetCursor (out path, out col);

			if (effetsListe.Columns [0] == col) {
				sequenceur.IndexLigneaSuivre = IndexEffetSelectionne();
			}
		}




		protected void OnBtnCommandClicked (object sender, EventArgs e)
		{
			sequenceur.CommandDirecte(txtCommand.Text );

		}


		


	
	}
}

