using System;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Threading;

using System.Printing;

using miew.String;
using miew.Enumerable;
using miew.Lambda;
using agree;

using ActiproSoftware.Windows.Controls.Docking;
using ActiproSoftware.Windows.Controls.Ribbon;
using ActiproSoftware.Windows.Controls.Ribbon.Controls;


namespace agree.Wpf
{

	public class GrammarTree : TreeViewItem
	{
		Grammar g;

		public GrammarTree(Grammar g)
		{
			if (String.IsNullOrEmpty(g.SysObjDescription))
				this.Header = g.SysObjName;
			else
			{
				TextBlock tb = new TextBlock();
				tb.Inlines.Add(g.SysObjName + " ");
				Span sp = new Span();
				sp.Foreground = Brushes.DarkRed;
				sp.Inlines.Add(g.SysObjDescription);
				tb.Inlines.Add(sp);
				this.Header = tb;
			}
			this.g = g;

			TreeViewItem tvi1, tvi2, tvi3;

			tvi1 = new TreeViewItem();
			tvi1.Header = "Types (Expanded)";
			{
				tvi2 = new TreeViewItem();
				tvi2.Header = "Authored Types";
				tvi2.Expanded += new RoutedEventHandler(tvi_expand_authored_type);
				tvi2.Collapsed += new RoutedEventHandler(tvi_collapse);
				tvi2.Items.Add(new TreeViewInstanceDummy());
				tvi1.Items.Add(tvi2);

				tvi2 = new TreeViewItem();
				tvi2.Header = "Glb Types";
				tvi2.Expanded += new RoutedEventHandler(tvi_expand_glb_type);
				tvi2.Collapsed += new RoutedEventHandler(tvi_collapse);
				tvi2.Items.Add(new TreeViewInstanceDummy());
				tvi1.Items.Add(tvi2);
			}
			this.Items.Add(tvi1);

			tvi1 = new TreeViewItem();
			tvi1.Header = String.Format("Features ({0})", g.tm.feat_arr.Length);
			tvi1.Expanded += new RoutedEventHandler((sender, e) =>
			{
				TreeViewItem tvi = (TreeViewItem)sender;
				if (tvi.Items[0] is TreeViewInstanceDummy)
				{
					tvi.Items.Clear();
					foreach (FeatureInfo fi in g.tm.feat_arr)
					{
						TreeViewItem tvic = new TreeViewItem();
						tvic.Header = String.Format("{0} ({1})", fi.feature.ToUpper(), fi.maximal_type.Name);
						tvi.Items.Add(tvic);
					}
				}
			});
			tvi1.Items.Add(new TreeViewInstanceDummy());
			this.Items.Add(tvi1);

			tvi1 = new TreeViewItem();
			tvi1.Header = "Entries (Expanded)";
			{
				tvi2 = new TreeViewItem();
				tvi2.Header = String.Format("Syntax Rules ({0})", g.tm.AllEntries.OfType<GrammarRule>().Count());
				tvi2.Expanded += new RoutedEventHandler(tvi_expand_instance<GrammarRule>);
				tvi2.Items.Add(new TreeViewInstanceDummy());
				tvi1.Items.Add(tvi2);

				tvi2 = new TreeViewItem();
				tvi2.Header = "Lexical Rules";
				{
					tvi3 = new TreeViewItem();
					tvi3.Header = "Non-affixing";
					tvi3.Expanded += new RoutedEventHandler(tvi_expand_instance<LexicalRule>);
					tvi3.Collapsed += new RoutedEventHandler(tvi_collapse);
					tvi3.Items.Add(new TreeViewInstanceDummy());
					tvi2.Items.Add(tvi3);

					tvi3 = new TreeViewItem();
					tvi3.Header = "Regular Affixing";
					tvi3.Expanded += new RoutedEventHandler(tvi_expand_instance<MorphologicalRule>);
					tvi3.Collapsed += new RoutedEventHandler(tvi_collapse);
					tvi3.Items.Add(new TreeViewInstanceDummy());
					tvi2.Items.Add(tvi3);

					tvi3 = new TreeViewItem();
					tvi3.Header = "Irregular Affixing";
					//tvi3.Expanded += new RoutedEventHandler(tvi_expand_authored_type);
					//tvi3.Collapsed += new RoutedEventHandler(tvi_collapse);
					tvi3.Items.Add(new TreeViewInstanceDummy());
					tvi2.Items.Add(tvi3);
				}
				tvi1.Items.Add(tvi2);

				tvi2 = new TreeViewItem();
				tvi2.Header = String.Format("Lexical Entries ({0})", g.tm.AllEntries.OfType<LexicalEntry>().Count());
				tvi2.Expanded += new RoutedEventHandler(tvi_expand_instance<LexicalEntry>);
				tvi2.Collapsed += new RoutedEventHandler(tvi_collapse);
				tvi2.Items.Add(new TreeViewInstanceDummy());
				tvi1.Items.Add(tvi2);

				tvi2 = new TreeViewItem();
				tvi2.Header = String.Format("Node Labels ({0})", g.tm.AllEntries.OfType<NodeLabel>().Count());
				tvi2.Expanded += new RoutedEventHandler(tvi_expand_instance<NodeLabel>);
				tvi2.Items.Add(new TreeViewInstanceDummy());
				tvi1.Items.Add(tvi2);

				tvi2 = new TreeViewItem();
				tvi2.Header = String.Format("Start Symbols ({0})", g.tm.AllEntries.OfType<StartSymbol>().Count());
				tvi2.Expanded += new RoutedEventHandler(tvi_expand_instance<StartSymbol>);
				tvi2.Items.Add(new TreeViewInstanceDummy());
				tvi1.Items.Add(tvi2);
			}
			this.Items.Add(tvi1);


			tvi1 = new TreeViewItem();
			tvi1.Header = "Definitions";
			{
				tvi2 = new TreeViewItem();
				tvi2.Header = "Type Definitions";
				tvi2.Expanded += new RoutedEventHandler(tvi_expand_instance_def<agree.Type>);
				tvi2.Collapsed += new RoutedEventHandler(tvi_collapse);
				tvi2.Items.Add(new TreeViewInstanceDummy());
				tvi1.Items.Add(tvi2);

				tvi2 = new TreeViewItem();
				tvi2.Header = "Entry Definitions";
				tvi2.Expanded += new RoutedEventHandler(tvi_expand_instance<agree.Entry>);
				tvi2.Collapsed += new RoutedEventHandler(tvi_collapse);
				tvi2.Items.Add(new TreeViewInstanceDummy());
				tvi1.Items.Add(tvi2);
			}
			this.Items.Add(tvi1);
		}

		TreeViewItem _parses = null;
		public TreeViewItem Parses
		{
			get
			{
				if (_parses == null)
				{
					_parses = new TreeViewItem();
					_parses.Header = "Parses";
					this.Items.Add(_parses);
				}
				return _parses;
			}
		}

		class TreeViewInstanceDummy : TreeViewItem { }
		class TreeViewInstanceType : TreeViewItem
		{
			agree.Instance t;
			public TreeViewInstanceType(agree.Instance t)
			{
				this.t = t;
			}
			public agree.Instance Type { get { return t; } }
		};

		void tvi_collapse(object sender, RoutedEventArgs e)
		{
			TreeViewItem tvi = (TreeViewItem)sender;
			tvi.Items.Add(new TreeViewInstanceDummy());
		}

		void tvi_expand_glb_type(object sender, RoutedEventArgs e)
		{
			TreeViewItem tvi = (TreeViewItem)sender;
			if (tvi.Items[0] is TreeViewInstanceDummy)
			{
				tvi.Items.Clear();
				foreach (agree.Type t in g.tm.AllTypes.Where(_t => _t.IsGlb))
				{
					TreeViewInstanceType tvic = new TreeViewInstanceType(t);
					String n = t.Parents.Select(p => p.Name).StringJoin(" ⊓ ");
					tvic.Header = String.Format("{0} ({1})", t.Name, n);
					tvic.MouseDoubleClick += new MouseButtonEventHandler(tvi_activate_type_expanded);
					tvi.Items.Add(tvic);
				}
			}
		}

		void tvi_expand_authored_type(object sender, RoutedEventArgs e)
		{
			TreeViewItem tvi = (TreeViewItem)sender;
			if (tvi.Items[0] is TreeViewInstanceDummy)
			{
				tvi.Items.Clear();
				foreach (agree.Type t in g.tm.AllTypes.Where(_t => !_t.IsGlb))
				{
					TreeViewInstanceType tvic = new TreeViewInstanceType(t);
					tvic.Header = t.Name;
					tvic.MouseDoubleClick += new MouseButtonEventHandler(tvi_activate_type_expanded);
					tvi.Items.Add(tvic);
				}
			}
		}

		void tvi_expand_instance<T>(object sender, RoutedEventArgs e) where T : agree.Instance
		{
			TreeViewItem tvi = (TreeViewItem)sender;
			if (tvi.Items[0] is TreeViewInstanceDummy)
			{
				tvi.Items.Clear();
				foreach (agree.Instance t in g.tm.AllInstances.OfExactType<T>().OrderBy(_t => _t.Name))
				{
					TreeViewInstanceType tvic = new TreeViewInstanceType(t);
					tvic.Header = t.Name;
					tvic.MouseDoubleClick += new MouseButtonEventHandler(tvi_activate_type_expanded);
					tvi.Items.Add(tvic);
				}
			}
		}

		void tvi_expand_instance_def<T>(object sender, RoutedEventArgs e) where T : agree.Instance
		{
			TreeViewItem tvi = (TreeViewItem)sender;
			if (tvi.Items[0] is TreeViewInstanceDummy)
			{
				tvi.Items.Clear();
				foreach (agree.Instance t in g.tm.AllInstances.OfExactType<T>().OrderBy(_t => _t.Name))
				{
					TreeViewInstanceType tvic = new TreeViewInstanceType(t);
					tvic.Header = t.Name;
					tvic.MouseDoubleClick += new MouseButtonEventHandler(tvi_activate_type_definition);
					tvi.Items.Add(tvic);
				}
			}
		}


#if false
		void tvi_expand_type<T>(object sender, RoutedEventArgs e)
		{
			TreeViewItem tvi = (TreeViewItem)sender;
			if (tvi.Items[0] is TreeViewInstanceDummy)
			{
				tvi.Items.Clear();
				foreach (agree.Type t in g.tm.AllTypes.Where(_t => _t is T).OrderBy(_t=>_t.Name))
				{
					TreeViewItemType tvic = new TreeViewItemType(t);
					tvic.Header = t.Name;
					tvic.MouseDoubleClick += new MouseButtonEventHandler(tvi_activate_type);
					//tvic.CommandBindings.Add(
					tvi.Items.Add(tvic);
				}
			}
		}
#endif

		void tvi_activate_type_expanded(object sender, MouseButtonEventArgs e)
		{
			TreeViewInstanceType tvi = sender as TreeViewInstanceType;
			if (tvi == null)
			{
				MessageBox.Show(String.Format("Cannot activate object of type '{0}'", tvi.GetType().Name));
				return;
			}

			System.Type t_cmd;
			if (MainWindow.optionSetting3d.Value)
				t_cmd = typeof(Open3dWindow);
			else
				t_cmd = typeof(ShowItemCommand);

			var q = MyDockSite.g_docksite.CommandBindings.OfType<CommandBinding>();
			var r = q.First(cb => cb.Command.GetType() == t_cmd);
			r.Command.Execute(tvi.Type);

			e.Handled = true;
		}

		void tvi_activate_type_definition(object sender, MouseButtonEventArgs e)
		{
			TreeViewInstanceType tvi = sender as TreeViewInstanceType;
			if (tvi == null)
			{
				MessageBox.Show(String.Format("Cannot activate object of type '{0}'", tvi.GetType().Name));
				return;
			}

			ShowItemCommand.BetterExecute(null, tvi.Type.Definition);
			e.Handled = true;
		}


#if false
		void tvi_expand_definitions<T>(object sender, RoutedEventArgs e)
		{
			TreeViewItem tvi = (TreeViewItem)sender;
			if (tvi.Items[0] is TreeViewItemDummy)
			{
				tvi.Items.Clear();
				foreach (Edge e in MainWindow.g.tm.AllTypes.Se)
				{
					TreeViewItem tvic = new TreeViewItem();
					tvic.Header = t.Name;
					tvi.Items.Add(tvic);
				}
			}
		}
#endif


	};


	public class ParseChartTree : TreeViewItem
	{
		ParseControl ctrl;
		ParseChart pc;

		public ParseChartTree(ParseControl ctrl)
		{
			MyDockSite mds = MyDockSite.g_docksite;

			this.ctrl = ctrl;
			this.pc = ctrl.chart;
			this.IsExpanded = true;
			this.ContextMenu = Anon<System.Windows.Controls.ContextMenu>.New(cm =>
				{
					cm.Items.Add(Anon<MenuItem>.New(mi =>
						{
							mi.Header = "Parse Trees";
							mi.Click += (o, e) =>
								{
									AgreeGrammarDocument etw = mds.DocumentWindows.OfType<MultiParseTreeWindow>().FirstOrDefault(d => d.ParseChart == pc);
									if (etw == null)
									{
										etw = new MultiParseTreeWindow(ctrl);
										mds.wksp.tmc.Items.Add(etw);
									}
									etw.Activate();
								};
						}));
					cm.Items.Add(Anon<MenuItem>.New(mi =>
					{
						mi.Header = "Parse Chart";
						mi.Click += (o, e) =>
						{
							AgreeGrammarDocument etw = mds.DocumentWindows.OfType<ParseChartWindow>().FirstOrDefault(d => d.ParseChart == pc);
							if (etw == null)
							{
								etw = new ParseChartWindow(ctrl,null);
								mds.wksp.tmc.Items.Add(etw);
							}
							etw.Activate();
						};
					}));
				});

			this.MouseDoubleClick += (o, e) =>
				{
					MainWindow.w.cmd_responders[ctrl.g].QueueResultContinuation(new SysCommands.CmdTokShowItem(ctrl.g, ctrl));
					e.Handled = true;
				};

			if (String.IsNullOrEmpty(ctrl.SysObjDescription))
				this.Header = ctrl.SysObjName;
			else
			{
				TextBlock tb = new TextBlock();
				tb.Inlines.Add(ctrl.SysObjName + " ");
				Span sp = new Span();
				sp.Foreground = Brushes.DarkRed;
				sp.Inlines.Add("\"" + ctrl.SysObjDescription + "\"");
				tb.Inlines.Add(sp);
				this.Header = tb;
			}

			foreach (var _p in pc.AllDerivations)
			{
				IDerivation cp = _p;	// closure copy
				TreeViewItem tvi1 = new TreeViewItem();
				tvi1.Header = cp.UnpackedTfs.Name;
				tvi1.IsExpanded = true;

				tvi1.ContextMenu = Anon<System.Windows.Controls.ContextMenu>.New(cm =>
				{
					cm.Items.Add(Anon<MenuItem>.New(mi =>
					{
						mi.Header = "Parse Tree";
						mi.Click += (o, e) =>
						{
							ParseTreeWindow etw = mds.DocumentWindows.OfType<ParseTreeWindow>().FirstOrDefault(d => d.ParseTree == cp);
							if (etw == null)
							{
								etw = new ParseTreeWindow(ctrl, cp);
								mds.wksp.tmc.Items.Add(etw);
							}
							etw.Activate();
						};
					}));
					cm.Items.Add(Anon<MenuItem>.New(mi =>
					{
						mi.Header = "Parse Chart";
						mi.Click += (o, e) =>
						{
							IEnumerable<IDerivation> use_edges = ((PassiveEdge.ParseTree)cp).DescendantsAndSelf;
							AgreeGrammarDocument etw=null;// = mds.DocumentWindows.OfType<ParseChartWindow>().FirstOrDefault(d => d.ParseChart == pc);
							if (etw == null)
							{
								etw = new ParseChartWindow(ctrl, use_edges);
								mds.wksp.tmc.Items.Add(etw);
							}
							etw.Activate();
						};
					}));
					cm.Items.Add(Anon<MenuItem>.New(mi =>
					{
						mi.Header = "TFS";
						mi.Click += (o, e) =>
						{
							Tfs tfs = (Tfs)cp;
							var etw = new ExpandedWindow(tfs);
							mds.wksp.tmc.Items.Add(etw);
							etw.Activate();
						};
					}));
				});

				tvi1.PreviewMouseDoubleClick += (o, e) =>
				{
					MainWindow.w.cmd_responders[ctrl].QueueResultContinuation(new SysCommands.CmdTokShowItem(ctrl, cp));
					e.Handled = true;
				};
				this.Items.Add(tvi1);
			}
		}
	};


	public class ObjectBrowserToolWindow : ToolWindow
	{
		TreeView m_tv;

		public ObjectBrowserToolWindow(DockSite ds)
			: base(ds)
		{
			this.Title = "Grammar Object Browser";

			m_tv = new TreeView();
			m_tv.SetValue(VirtualizingStackPanel.IsVirtualizingProperty, true);
			this.Content = m_tv;
		}

		Dictionary<ISysObj, GrammarTree> grammar_tree_dict = new Dictionary<ISysObj, GrammarTree>();

		public void AddSysObj(ISysObj iso)
		{
			Grammar ig = iso as Grammar;
			if (ig != null)
			{
				GrammarTree gt = new GrammarTree(ig);
				gt.IsExpanded = true;
				m_tv.Items.Add(gt);

				grammar_tree_dict.Add(iso, gt);
				return;
			}
			ParseChart pc = iso as ParseChart;
			if (pc != null)
			{
				ParseChartTree pct = new ParseChartTree(pc.ctrl);
				grammar_tree_dict[iso.SysObjParent].Parses.Items.Add(pct);

				return;
			}
		}
	};
}