/*
 *  TLV - Trace Log Visualizer
 *
 *  Copyright (C) 2008-2010 by Nagoya Univ., JAPAN
 *
 *  上記著作権者は，以下の(1)〜(4)の条件を満たす場合に限り，本ソフトウェ
 *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
 *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
 *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
 *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
 *      スコード中に含まれていること．
 *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
 *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
 *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
 *      の無保証規定を掲載すること．
 *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
 *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
 *      と．
 *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
 *        作権表示，この利用条件および下記の無保証規定を掲載すること．
 *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
 *        報告すること．
 *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
 *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
 *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
 *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
 *      免責すること．
 *
 *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
 *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
 *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
 *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
 *  の責任を負わない．
 *
 *  @(#) $Id$
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using NU.OJL.MPRTOS.TLV.Core;
using System.Text.RegularExpressions;
using NU.OJL.MPRTOS.TLV.Base.Controls;
using System.Collections;
using NU.OJL.MPRTOS.TLV.Base;

namespace NU.OJL.MPRTOS.TLV.Core.Controls
{
	public partial class ResourceExplorer : Form, ITraceLogVisualizerControl
	{
		protected TraceLogVisualizerData _data;
		private Dictionary<string, TreeView> _treeViews = new Dictionary<string, TreeView>();

		public ResourceExplorer()
		{
			TopLevel = false;
			InitializeComponent();
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);

			imageList.Images.Add("resource", Properties.Resources.resource);
			imageList.Images.Add("resources", Properties.Resources.resources);

			tabControl.MouseEnter += delegate(object o, EventArgs _e)
			{
				ApplicationFactory.StatusManager.ShowHint(tabControl.GetType().ToString() + ":checkIs", "分類切替え", "クリック");
			};
			tabControl.MouseLeave += delegate(object o, EventArgs _e)
			{
				ApplicationFactory.StatusManager.HideHint(tabControl.GetType().ToString() + ":checkIs");
			};
			tabControl.LostFocus += delegate(object o, EventArgs _e)
			{
				ApplicationFactory.StatusManager.HideHint(tabControl.GetType().ToString() + ":checkIs");
			};
		}

		public void SetData(TraceLogVisualizerData data)
		{
			_data = data;
			ResourceData resourceData = data.ResourceData;

			ClearData();

			List<NamedResourceList> resTypeClass = new List<NamedResourceList>();

			foreach (ResourceType resType in resourceData.ResourceHeaders.ResourceTypes)
			{
				NamedResourceList list = new NamedResourceList();
				list.Name = resType.Name;
				list.DisplayName = resType.DisplayName;
				list.List = Where<Resource>(resourceData.Resources, delegate(Resource r) { return r.Type == resType.Name; });
				resTypeClass.Add(list);
			}

			setData("___resType", "リソースタイプ", resTypeClass);

			foreach (ResourceType resType in resourceData.ResourceHeaders.ResourceTypes)
			{
				foreach (AttributeType attr in Where<AttributeType>(resType.Attributes, delegate(AttributeType a) { return a.CanGrouping == true; }))
				{
					List<NamedResourceList> datas = new List<NamedResourceList>();

					foreach (Resource res in Where<Resource>(resourceData.Resources, delegate(Resource r) { return r.Attributes.ContainsKey(attr.Name); }))
					{
						string value = res.Attributes[attr.Name].Value.ToString();
						if (!Any<NamedResourceList>(datas, delegate(NamedResourceList d) { return d.Name == value; }))
						{
							NamedResourceList list = new NamedResourceList();
							list.Name = value;
							list.DisplayName = value;
							list.List = OrderBy<Resource, object>(Where<Resource>(resourceData.Resources, delegate(Resource r)
								{
									return r.Attributes.ContainsKey(attr.Name) && r.Attributes[attr.Name].Value.ToString() == value;
								}), delegate(Resource r) { return r.Attributes[attr.Name].Value; });
							datas.Add(list);
						}
					}
					datas.Sort(delegate(NamedResourceList n1, NamedResourceList n2)
						{
							switch (attr.VariableType)
							{
								case NU.OJL.MPRTOS.TLV.Base.JsonValueType.Number:
									return Convert.ToDecimal(n1.Name).CompareTo(Convert.ToDecimal(n2.Name));
								default:
									return n1.Name.CompareTo(n1.Name);
							}
						});
					setData(attr.Name, attr.DisplayName, datas);
				}
			}

			foreach (TreeView tv in _treeViews.Values)
			{
				tv.MouseEnter += delegate(object o, EventArgs e)
				{
					ApplicationFactory.StatusManager.ShowHint(tv.GetType().ToString() + ":checkIs", "可視化表示", "チェック");
				};
				tv.MouseLeave += delegate(object o, EventArgs e)
				{
					ApplicationFactory.StatusManager.HideHint(tv.GetType().ToString() + ":checkIs");
				};
				tv.LostFocus += delegate(object o, EventArgs e)
				{
					ApplicationFactory.StatusManager.HideHint(tv.GetType().ToString() + ":checkIs");
				};

				tv.AfterCheck += delegate(object o, TreeViewEventArgs e)
				{
					if (e.Node.Level == 1)
					{
						setVisibility(e.Node.Checked, e.Node.Name);
					}
				};

				tv.ExpandAll();
			}

			_data.SettingData.ResourceExplorerSetting.BecameDirty += delegate(object _o, string __e)
			{
				foreach (KeyValuePair<string, bool> kvp in (IList)_o)
				{
					foreach (TreeView tv in _treeViews.Values)
					{
						foreach (TreeNode tn in tv.Nodes)
						{
							foreach (TreeNode _tn in tn.Nodes.Find(kvp.Key, false))
							{
								if (_tn.Checked != kvp.Value)
									_tn.Checked = kvp.Value;
							}
						}
					}
				}
			};
		}

		private void setVisibility(bool value, string keys)
		{
			if (_data.SettingData.ResourceExplorerSetting.ResourceVisibility.ContainsKey(keys)
				&& (_data.SettingData.ResourceExplorerSetting.ResourceVisibility.GetValue(keys) == value))
			{
				return;
			}
			else
			{
				ApplicationFactory.CommandManager.Do(new GeneralCommand(Text + " 可視化表示リソース切替え",
					delegate() { _data.SettingData.ResourceExplorerSetting.ResourceVisibility.SetValue(value, keys); },
					delegate() { _data.SettingData.ResourceExplorerSetting.ResourceVisibility.SetValue(!value, keys); }));
			}
		}

		private void setData(string name, string displayName, List<NamedResourceList> groups)
		{
			tabControl.TabPages.Add(name, displayName + "別");
			ExTreeView treeView = new ExTreeView();
			treeView.ImageList = imageList;
			treeView.Dock = DockStyle.Fill;
			treeView.CheckBoxes = true;
			treeView.Name = name;
			foreach (NamedResourceList group in groups)
			{
				treeView.Nodes.Add(name + ":" + group.Name, group.DisplayName);
				treeView.Nodes[name + ":" + group.Name].ImageKey = "resources";
				treeView.Nodes[name + ":" + group.Name].SelectedImageKey = "resources";

				foreach (Resource res in group.List)
				{
					treeView.Nodes[name + ":" + group.Name].Nodes.Add(res.Name, res.DisplayName);
					treeView.Nodes[name + ":" + group.Name].Nodes[res.Name].ImageKey = "resource";
					treeView.Nodes[name + ":" + group.Name].Nodes[res.Name].SelectedImageKey = "resource";

					treeView.Nodes[name + ":" + group.Name].Nodes[res.Name].Checked = _data.SettingData.ResourceExplorerSetting.ResourceVisibility.ContainsKey(res.Name) ? _data.SettingData.ResourceExplorerSetting.ResourceVisibility.GetValue(res.Name) : ApplicationData.Setting.DefaultResourceVisible;

					if (!_data.SettingData.ResourceExplorerSetting.ResourceVisibility.ContainsKey(res.Name))
					{
						_data.SettingData.ResourceExplorerSetting.ResourceVisibility.SetValue(ApplicationData.Setting.DefaultResourceVisible, res.Name);
					}
				}
			}
			tabControl.TabPages[name].Controls.Add(treeView);

			_treeViews.Add(name, treeView);
		}

		public void ClearData()
		{
			tabControl.TabPages.Clear();
			_treeViews.Clear();
		}

		private static List<T> OrderBy<T, K>(IEnumerable<T> objs, Func<T, K> p)
		{
			List<T> result = new List<T>(objs);
			IComparer<K> comparer = Comparer<K>.Default;
			result.Sort(delegate(T t1, T t2) { return comparer.Compare(p(t1), p(t2)); });
			return result;
		}

		private static bool Any<T>(IEnumerable<T> objs, Func<T, bool> p)
		{
			foreach (T obj in objs)
			{
				if (p(obj))
					return true;
			}
			return false;
		}

		private static List<T> Where<T>(IEnumerable<T> objs, Func<T, bool> p)
		{
			List<T> result = new List<T>();
			foreach (T obj in objs)
			{
				if (p(obj))
					result.Add(obj);
			}
			return result;
		}
	}

	class NamedResourceList
	{
		private string _Name;
		private string _DisplayName;
		private List<Resource> _List;
		public string Name { get { return _Name; } set { _Name = value; } }
		public string DisplayName { get { return _DisplayName; } set { _DisplayName = value; } }
		public List<Resource> List { get { return _List; } set { _List = value; } }
	}
}
