using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using nft.framework;
using nft.framework.plugin;
using nft.ui.command;
using nft.util;
using nft.win32util;
using nft.controls;
using System.IO;
using System.Diagnostics;

namespace nft.ui.system
{
	/// <summary>
	/// PluginListDialog の概要の説明です。
	/// </summary>
	public class PluginListDialog : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Panel panel1;
		private System.Windows.Forms.Button button1;
		private System.Windows.Forms.ColumnHeader titleColumn;
		private System.Windows.Forms.ColumnHeader authorColumn;
		private System.Windows.Forms.TabControl tabControl1;
		private System.Windows.Forms.TabPage tabPage1;
		private System.Windows.Forms.TabPage tabPage2;
		private System.Windows.Forms.ColumnHeader columnHeader1;
		private System.Windows.Forms.ColumnHeader columnHeader2;
		private System.Windows.Forms.ColumnHeader columnHeader3;
		private System.Windows.Forms.ListView plist;
		private System.Windows.Forms.TreeView tree;
		private System.Windows.Forms.ListView clist;
		private UrlLinkLabel info;
		private System.Windows.Forms.ColumnHeader pathColumn;
		private System.Windows.Forms.ImageList image;
		private nft.controls.MsgAndIconLabel labelMsg;
        private ContextMenuStrip pluginCtxMenu;
        private ToolStripMenuItem pluginCtxMenu_OpenFile;
        private ToolStripMenuItem pluginCtxMenu_OpenByExplorer;
        private ToolStripMenuItem pluginCtxMenu_CopyURI;
		private System.ComponentModel.IContainer components;

		public PluginListDialog()
		{
			//
			// Windows フォーム デザイナ サポートに必要です。
			//
			InitializeComponent();
			labelMsg.ImageList = UIUtil.MsgTypeIcons;
			ShowInfoMessage();

			plist.ListViewItemSorter = new Sorter(0,false);
			clist.ListViewItemSorter = new Sorter(0,false);
			string filename = Directories.SystemResourceDir+"plugin_icons.bmp";
			image.Images.AddStrip(new System.Drawing.Bitmap(filename));
		}

		/// <summary>
		/// 使用されているリソースに後処理を実行します。
		/// </summary>
		protected override void Dispose( bool disposing ) {
			if( disposing && components != null)
				components.Dispose();
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
		/// コード エディタで変更しないでください。
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("ノード0");
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PluginListDialog));
            this.panel1 = new System.Windows.Forms.Panel();
            this.button1 = new System.Windows.Forms.Button();
            this.plist = new System.Windows.Forms.ListView();
            this.titleColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.authorColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.pathColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.image = new System.Windows.Forms.ImageList(this.components);
            this.tree = new System.Windows.Forms.TreeView();
            this.tabControl1 = new System.Windows.Forms.TabControl();
            this.tabPage1 = new System.Windows.Forms.TabPage();
            this.clist = new System.Windows.Forms.ListView();
            this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.tabPage2 = new System.Windows.Forms.TabPage();
            this.pluginCtxMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.pluginCtxMenu_OpenFile = new System.Windows.Forms.ToolStripMenuItem();
            this.pluginCtxMenu_OpenByExplorer = new System.Windows.Forms.ToolStripMenuItem();
            this.pluginCtxMenu_CopyURI = new System.Windows.Forms.ToolStripMenuItem();
            this.info = new nft.controls.UrlLinkLabel();
            this.labelMsg = new nft.controls.MsgAndIconLabel();
            this.panel1.SuspendLayout();
            this.tabControl1.SuspendLayout();
            this.tabPage1.SuspendLayout();
            this.tabPage2.SuspendLayout();
            this.pluginCtxMenu.SuspendLayout();
            this.SuspendLayout();
            // 
            // panel1
            // 
            this.panel1.Controls.Add(this.labelMsg);
            this.panel1.Controls.Add(this.button1);
            this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.panel1.Location = new System.Drawing.Point(0, 277);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(432, 32);
            this.panel1.TabIndex = 0;
            // 
            // button1
            // 
            this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.button1.DialogResult = System.Windows.Forms.DialogResult.OK;
            this.button1.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.button1.Location = new System.Drawing.Point(336, 4);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(88, 24);
            this.button1.TabIndex = 0;
            this.button1.Text = "&OK";
            // 
            // plist
            // 
            this.plist.AllowColumnReorder = true;
            this.plist.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.plist.CheckBoxes = true;
            this.plist.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            this.titleColumn,
            this.authorColumn,
            this.pathColumn});
            this.plist.FullRowSelect = true;
            this.plist.HideSelection = false;
            this.plist.Location = new System.Drawing.Point(0, 0);
            this.plist.Name = "plist";
            this.plist.Size = new System.Drawing.Size(424, 151);
            this.plist.SmallImageList = this.image;
            this.plist.TabIndex = 1;
            this.plist.UseCompatibleStateImageBehavior = false;
            this.plist.View = System.Windows.Forms.View.Details;
            this.plist.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.list_ColumnClick);
            this.plist.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.list_ItemCheck);
            this.plist.SelectedIndexChanged += new System.EventHandler(this.plist_SelectedIndexChanged);
            this.plist.MouseClick += new System.Windows.Forms.MouseEventHandler(this.plist_MouseClick);
            // 
            // titleColumn
            // 
            this.titleColumn.Text = "プラグイン";
            this.titleColumn.Width = 150;
            // 
            // authorColumn
            // 
            this.authorColumn.Text = "製作者";
            this.authorColumn.Width = 80;
            // 
            // pathColumn
            // 
            this.pathColumn.Text = "場所";
            this.pathColumn.Width = 500;
            // 
            // image
            // 
            this.image.ColorDepth = System.Windows.Forms.ColorDepth.Depth16Bit;
            this.image.ImageSize = new System.Drawing.Size(16, 16);
            this.image.TransparentColor = System.Drawing.Color.Magenta;
            // 
            // tree
            // 
            this.tree.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.tree.CheckBoxes = true;
            this.tree.HideSelection = false;
            this.tree.ImageIndex = 0;
            this.tree.ImageList = this.image;
            this.tree.Location = new System.Drawing.Point(0, 0);
            this.tree.Name = "tree";
            treeNode1.Name = "";
            treeNode1.Text = "ノード0";
            this.tree.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode1});
            this.tree.SelectedImageIndex = 0;
            this.tree.Size = new System.Drawing.Size(424, 199);
            this.tree.TabIndex = 1;
            this.tree.BeforeCheck += new System.Windows.Forms.TreeViewCancelEventHandler(this.tree_BeforeCheck);
            this.tree.BeforeExpand += new System.Windows.Forms.TreeViewCancelEventHandler(this.tree_BeforeExpand);
            this.tree.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.tree_AfterSelect);
            this.tree.MouseClick += new System.Windows.Forms.MouseEventHandler(this.tree_Click);
            // 
            // tabControl1
            // 
            this.tabControl1.Appearance = System.Windows.Forms.TabAppearance.Buttons;
            this.tabControl1.Controls.Add(this.tabPage1);
            this.tabControl1.Controls.Add(this.tabPage2);
            this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.tabControl1.Location = new System.Drawing.Point(0, 0);
            this.tabControl1.Name = "tabControl1";
            this.tabControl1.SelectedIndex = 0;
            this.tabControl1.Size = new System.Drawing.Size(432, 277);
            this.tabControl1.TabIndex = 2;
            this.tabControl1.SelectedIndexChanged += new System.EventHandler(this.tabControl1_SelectedIndexChanged);
            // 
            // tabPage1
            // 
            this.tabPage1.Controls.Add(this.clist);
            this.tabPage1.Controls.Add(this.plist);
            this.tabPage1.Location = new System.Drawing.Point(4, 25);
            this.tabPage1.Name = "tabPage1";
            this.tabPage1.Size = new System.Drawing.Size(424, 248);
            this.tabPage1.TabIndex = 0;
            this.tabPage1.Text = "ファイル別表示";
            // 
            // clist
            // 
            this.clist.AllowColumnReorder = true;
            this.clist.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.clist.CheckBoxes = true;
            this.clist.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            this.columnHeader1,
            this.columnHeader2,
            this.columnHeader3});
            this.clist.FullRowSelect = true;
            this.clist.Location = new System.Drawing.Point(0, 152);
            this.clist.Name = "clist";
            this.clist.Size = new System.Drawing.Size(424, 96);
            this.clist.SmallImageList = this.image;
            this.clist.TabIndex = 2;
            this.clist.UseCompatibleStateImageBehavior = false;
            this.clist.View = System.Windows.Forms.View.Details;
            this.clist.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.list_ColumnClick);
            this.clist.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.list_ItemCheck);
            this.clist.SelectedIndexChanged += new System.EventHandler(this.list_SelectedIndexChenged);
            // 
            // columnHeader1
            // 
            this.columnHeader1.Text = "コントリビューション";
            this.columnHeader1.Width = 150;
            // 
            // columnHeader2
            // 
            this.columnHeader2.Text = "種類";
            this.columnHeader2.Width = 120;
            // 
            // columnHeader3
            // 
            this.columnHeader3.Text = "ID";
            this.columnHeader3.Width = 400;
            // 
            // tabPage2
            // 
            this.tabPage2.Controls.Add(this.info);
            this.tabPage2.Controls.Add(this.tree);
            this.tabPage2.Location = new System.Drawing.Point(4, 25);
            this.tabPage2.Name = "tabPage2";
            this.tabPage2.Size = new System.Drawing.Size(424, 248);
            this.tabPage2.TabIndex = 1;
            this.tabPage2.Text = "タイプ別表示";
            // 
            // pluginCtxMenu
            // 
            this.pluginCtxMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.pluginCtxMenu_OpenFile,
            this.pluginCtxMenu_OpenByExplorer,
            this.pluginCtxMenu_CopyURI});
            this.pluginCtxMenu.Name = "pluginCtxMenu";
            this.pluginCtxMenu.ShowImageMargin = false;
            this.pluginCtxMenu.Size = new System.Drawing.Size(184, 70);
            this.pluginCtxMenu.Opening += new System.ComponentModel.CancelEventHandler(this.pluginCtxMenu_Opening);
            // 
            // pluginCtxMenu_OpenFile
            // 
            this.pluginCtxMenu_OpenFile.Name = "pluginCtxMenu_OpenFile";
            this.pluginCtxMenu_OpenFile.Size = new System.Drawing.Size(183, 22);
            this.pluginCtxMenu_OpenFile.Text = "plugin.xmlを開く";
            this.pluginCtxMenu_OpenFile.Click += new System.EventHandler(this.pluginCtxMenu_OpenFile_Click);
            // 
            // pluginCtxMenu_OpenByExplorer
            // 
            this.pluginCtxMenu_OpenByExplorer.Name = "pluginCtxMenu_OpenByExplorer";
            this.pluginCtxMenu_OpenByExplorer.Size = new System.Drawing.Size(183, 22);
            this.pluginCtxMenu_OpenByExplorer.Text = "エクスプローラーで開く";
            this.pluginCtxMenu_OpenByExplorer.Click += new System.EventHandler(this.pluginCtxMenu_OpenByExplorer_Click);
            // 
            // pluginCtxMenu_CopyURI
            // 
            this.pluginCtxMenu_CopyURI.Name = "pluginCtxMenu_CopyURI";
            this.pluginCtxMenu_CopyURI.Size = new System.Drawing.Size(183, 22);
            this.pluginCtxMenu_CopyURI.Text = "URIをコピー";
            this.pluginCtxMenu_CopyURI.Click += new System.EventHandler(this.puginCtxMenu_CopyURI_Click);
            // 
            // info
            // 
            this.info.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.info.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.info.Location = new System.Drawing.Point(0, 208);
            this.info.Name = "info";
            this.info.Size = new System.Drawing.Size(424, 40);
            this.info.TabIndex = 2;
            this.info.TargetUrl = null;
            // 
            // labelMsg
            // 
            this.labelMsg.BackColor = System.Drawing.SystemColors.Control;
            this.labelMsg.ImageIndex = -1;
            this.labelMsg.ImageList = null;
            this.labelMsg.Location = new System.Drawing.Point(8, 0);
            this.labelMsg.Message = "";
            this.labelMsg.Name = "labelMsg";
            this.labelMsg.Size = new System.Drawing.Size(312, 32);
            this.labelMsg.TabIndex = 1;
            // 
            // PluginListDialog
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
            this.ClientSize = new System.Drawing.Size(432, 309);
            this.Controls.Add(this.tabControl1);
            this.Controls.Add(this.panel1);
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "PluginListDialog";
            this.Text = "インストールされているプラグイン";
            this.Load += new System.EventHandler(this.PluginListDialog_Load);
            this.panel1.ResumeLayout(false);
            this.tabControl1.ResumeLayout(false);
            this.tabPage1.ResumeLayout(false);
            this.tabPage2.ResumeLayout(false);
            this.pluginCtxMenu.ResumeLayout(false);
            this.ResumeLayout(false);

		}
		#endregion

		#region event handlers
		private void PluginListDialog_Load(object sender, System.EventArgs e) 
		{
			// populate the list
			clist.Items.Clear();
			plist.Items.Clear();
			foreach( Plugin p in PluginManager.theInstance.Plugins )
				plist.Items.Add( CreateListItem(p) );

			// construct tree
			tree.Nodes.Clear();
            foreach (KeyValuePair<string, IContributionFactory> fent in PluginManager.theInstance.Factories) {
                tree.Nodes.Add(CreateTreeItem(fent));
            }
            //foreach (Plugin p in PluginManager.theInstance.Plugins)
				//tree.Nodes.Add( CreateTreeItem(p) );
		}


        private void plist_MouseClick(object sender, MouseEventArgs e) {
            if (e.Button == MouseButtons.Right) {
                if (plist.FocusedItem.Bounds.Contains(e.Location) == true) {
                    pluginCtxMenu.Tag = plist.FocusedItem.Tag;
                    pluginCtxMenu.Show(Cursor.Position);
                }
            }
        }


        private void tree_Click(object sender, MouseEventArgs e) {
            if (e.Button == MouseButtons.Right) {
                TreeNode node = tree.GetNodeAt(e.Location);
                if (node!=null && node.Tag is Plugin) {
                    tree.SelectedNode = node;
                    pluginCtxMenu.Tag = node.Tag;
                    pluginCtxMenu.Show(Cursor.Position);
                }
            }
        }

		private void list_ColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e)
		{
			
			ListView _list = (ListView)sender;
			Sorter sorter = (Sorter)_list.ListViewItemSorter;
			sorter.index = e.Column;
			sorter.bNumeric = false;
			_list.Sort();		
		}

		private void plist_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			ShowInfoMessage();
			clist.Items.Clear();
			if( plist.SelectedItems.Count == 0 )
				return;
			//foreach( ListViewItem item in plist.SelectedItems )
			ListViewItem item = plist.SelectedItems[0];
			{
				Application.DoEvents();
				Plugin p = (Plugin)item.Tag;
                foreach (Contribution c in p.Contributions) {
                    clist.Items.Add(CreateListItem(c));
                }
            }
		}

		private void tree_BeforeExpand(object sender, System.Windows.Forms.TreeViewCancelEventArgs e)
		{
            IContributionFactory f = e.Node.Tag as IContributionFactory;
            if (f != null) {
                e.Node.Nodes.Clear();
                foreach (Contribution c in PluginManager.theInstance.EnumContributions(f.OutputType,false)) {
                    Plugin p = c.Parent;
                    TreeNode pnode = null;
                    foreach (TreeNode tn in e.Node.Nodes) {
                        if (tn.Tag == p) {
                            pnode = tn;
                            break;
                        }
                    }
                    if (pnode == null) {
                        pnode = CreateTreeItem(p);
                        e.Node.Nodes.Add(pnode);
                    }
                    pnode.Nodes.Add(CreateTreeItem(c));
                }
                return;
            }
            /*
            Plugin p = e.Node.Tag as Plugin;
			if(p!=null)
			{
				e.Node.Nodes.Clear();
                List<Contribution> prim = new List<Contribution>();
                foreach (Contribution c in p.Contributions) {
                    if (c.IsPrimitive) {
                        prim.Add(c);
                    } else {
                        e.Node.Nodes.Add(CreateTreeItem(c));
                    }
                }
                int i = 0;
                foreach (Contribution c in prim)
                    e.Node.Nodes.Insert(i++,CreateTreeItem(c));
            }
            */
		}

		private void tree_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
		{
			ShowInfoMessage();
			string msg;
            IContributionFactory f = e.Node.Tag as IContributionFactory;
            if (f != null) {
                string dllname = Path.GetFileName(new Uri(f.GetType().Assembly.CodeBase).LocalPath);
                msg = string.Format("Type:{0}\nFactory:{1}\nCodeBase:{2}", f.OutputType.Name, f.GetType().FullName, dllname);
                info.Text = msg;
                info.LinkArea = new LinkArea(0, 0);
                info.TargetUrl = "";
                return;
            } 
            Plugin p = e.Node.Tag as Plugin;
			if(p!=null)
			{
				msg = string.Format("Title:{0}\nAuthor:{1}\nHomepage:{2}",p.Title,p.author,p.homepage);
				info.Text = msg;
				if(p.homepage.Equals("N/A")||p.homepage.Trim().Length==0)
				{
					info.LinkArea = new LinkArea(0,0);
					info.TargetUrl="";
				}
				else
				{
					int n = p.homepage.Length;
					info.LinkArea = new LinkArea(msg.Length-n,n);
					info.TargetUrl=p.homepage;
				}
				return;
			}
			Contribution c = e.Node.Tag as Contribution;
			if(c!=null)
			{
                msg = string.Format("ID:{0}\nName:{1}\nDescription:{2}", c.ID, c.Name, c.Description);
				info.Text = msg;
				info.LinkArea = new LinkArea(0,0);
				info.TargetUrl="";
				return;
			}			
		}
		#endregion		

		private void ShowInfoMessage()
		{
			labelMsg.ImageIndex = (int)UIMessageType.info;
            labelMsg.Text = I18n.T("Uncheck to forbid cpu using this plug-in.");
		}
		private void ShowErrorMessage()
		{
			labelMsg.ImageIndex = (int)UIMessageType.alert;
            labelMsg.Text = I18n.T("This contribution cannot invalidate.");
			Win32Util.MessageBeep();
		}

		#region Item construction helpers.

		private int GetIconIndex(Contribution c)
		{
			switch(c.State)
			{
				case InstallationState.Ready:
                    if (c.IsPrimitive)	
						return 4;
					else
						return 1;
				default:
					return 2;
			}
		}

		private int GetIconIndex(Plugin p)
		{
			switch(p.State)
			{
				case InstallationState.Ready:
					return 0;
				case InstallationState.PartialError:
					return 3;
                case InstallationState.FatalError:
                    return 5;
				default:
					return 2;
			}
		}

		private ListViewItem CreateListItem(Contribution c)
		{
			int icon = GetIconIndex(c);
			ListViewItem item = new ListViewItem(new string[]{ c.Name ,c.CtbType, c.ID.AsString }, icon );
			item.Tag = c;
			item.Checked = c.IsAttached;
			return item;
		}
		private ListViewItem CreateListItem(Plugin p)
		{
			int icon = GetIconIndex(p);
			ListViewItem item = new ListViewItem(new string[]{ p.Title, p.author, p.ID.AsString }, icon );
			item.Tag = p;			
			item.Checked = p.IsAttached;
            
			return item;
		}
		private TreeNode CreateTreeItem(Contribution c)
		{
			int icon = GetIconIndex(c);
			TreeNode node = new TreeNode(c.Name, icon, icon );
			node.Tag = c;				
			node.Checked = c.IsAttached;
			return node;
		}

		private void tabControl1_SelectedIndexChanged(object sender, System.EventArgs e)
		{			
			switch(tabControl1.SelectedIndex )
			{
				case 0:
					foreach(ListViewItem item in plist.Items)
					{
						IAddable addable =item.Tag as IAddable;
						if(addable!=null && item.Checked!=addable.IsAttached)
							item.Checked = addable.IsAttached;
					}
					foreach(ListViewItem item in clist.Items)
					{
						IAddable addable =item.Tag as IAddable;
						if(addable!=null && item.Checked!=addable.IsAttached)
							item.Checked = addable.IsAttached;
					}
					break;
			
			
				case 1:
					foreach(TreeNode node in tree.Nodes)
					{
						IAddable addable =node.Tag as IAddable;
						if(addable!=null  && node.Checked!=addable.IsAttached)
							node.Checked = addable.IsAttached;
						foreach(TreeNode node2 in node.Nodes)
						{
							IAddable addable2 =node2.Tag as IAddable;
							if(addable2!=null  && node2.Checked!=addable2.IsAttached)
								node2.Checked = addable2.IsAttached;
						}
					}
					break;
			}

		}

		private void tree_BeforeCheck(object sender, System.Windows.Forms.TreeViewCancelEventArgs e)
		{
			TreeNode node = e.Node;
            Contribution addable = node.Tag as Contribution;
			 if(e.Action != TreeViewAction.ByMouse && e.Action !=TreeViewAction.ByKeyboard ) return;
             if (addable!=null && addable.IsDetachable)
			{
				if(node.Checked)
					addable.Detach();
				else
					addable.Attach();
				if(node.IsExpanded)
					foreach(TreeNode node2 in node.Nodes)
						node2.Checked = ((IAddable)node2.Tag).IsAttached;				
			}
			else
			{
				ShowErrorMessage();
				e.Cancel = true;
			}
		}

		private void list_SelectedIndexChenged(object sender, System.EventArgs e)
		{
			ShowInfoMessage();
		}

		private void list_ItemCheck(object sender, System.Windows.Forms.ItemCheckEventArgs e)
		{						
			ListView _list = (ListView)sender;
			ListViewItem item = _list.Items[e.Index];
			IAddable addable = item.Tag as IAddable;
			if( addable.IsAttached == (e.NewValue==CheckState.Checked) ) return;
			if( addable.IsDetachable )
			{
				if(e.NewValue==CheckState.Checked)
					addable.Attach();
				else if(e.NewValue==CheckState.Unchecked)
					addable.Detach();
				if(_list == plist)
					foreach(ListViewItem item2 in clist.Items)
						item2.Checked = ((IAddable)item2.Tag).IsAttached;
			}
			else
			{
				if(e.NewValue == CheckState.Unchecked)
				{
					ShowErrorMessage();
					e.NewValue = CheckState.Checked;
				}
			}
		}

		private void RefleshContribList()
		{
		}
	
		private TreeNode CreateTreeItem(KeyValuePair<string,IContributionFactory> kvp)
		{
            IContributionFactory f = kvp.Value;
            string caption;
            Contribution ctb = f as Contribution;
            if (ctb != null && ctb.Description != null && ctb.Description.Trim().Length>0 ) {
                caption = string.Format("{0}: {1}", kvp.Key, ctb.Description);
            } else {
                caption = kvp.Key;
            }
            int icon = 6;
            TreeNode node = new TreeNode(caption, icon, icon, new TreeNode[] { new TreeNode("") });
			node.Tag = f;
			node.Checked = true;
			return node;
		}
        private TreeNode CreateTreeItem(Plugin p) {
            int icon = GetIconIndex(p);
            TreeNode node = new TreeNode(p.ID.AsString, icon, icon);
            node.Tag = p;
            node.Checked = p.IsAttached;
            return node;
        }
        #endregion
		
		internal class Sorter : IComparer
		{
			public int index;
			public bool bNumeric;

			public Sorter(int idx, bool bNumeric) 
			{
				index = idx;
				this.bNumeric = bNumeric;
			}

			public int Compare( object x, object y)
			{
				string sx = ((ListViewItem)x).SubItems[index].Text;
				string sy = ((ListViewItem)y).SubItems[index].Text;
				if( bNumeric ) 
				{
					return (int)(double.Parse(sy.Replace("%",""))-double.Parse(sx.Replace("%","")));
				}
				else
					return string.Compare(sx,sy);
			}
		}

        private void pluginCtxMenu_OpenFile_Click(object sender, EventArgs e) {
            Debug.WriteLine(pluginCtxMenu_OpenFile.Tag);
            Process.Start(pluginCtxMenu_OpenFile.Tag as string);
        }

        private void pluginCtxMenu_OpenByExplorer_Click(object sender, EventArgs e) {
            if (pluginCtxMenu_OpenByExplorer.Tag != null) {
                Debug.WriteLine(pluginCtxMenu_OpenByExplorer.Tag);
                Process.Start("explorer.exe", "/e," + pluginCtxMenu_OpenByExplorer.Tag);
            }
        }

        private void puginCtxMenu_CopyURI_Click(object sender, EventArgs e) {
            Clipboard.SetText(pluginCtxMenu_CopyURI.Tag as string);
        }

        private void pluginCtxMenu_Opening(object sender, CancelEventArgs e) {
            try {
                Plugin p = pluginCtxMenu.Tag as Plugin;
                pluginCtxMenu_CopyURI.Tag = p.Uri.AbsoluteUri;
                Debug.WriteLine(p.Uri.AbsoluteUri);
                string localpath = p.Uri.LocalPath + Uri.UnescapeDataString(p.Uri.Fragment);
                pluginCtxMenu_OpenByExplorer.Enabled = Directory.Exists(localpath);
                if (pluginCtxMenu_OpenByExplorer.Enabled) {
                    pluginCtxMenu_OpenByExplorer.Tag = localpath;
                    pluginCtxMenu_OpenFile.Tag = Path.Combine(localpath, Plugin.PluginFileName);
                } else {
                    pluginCtxMenu_OpenByExplorer.Tag = null;
                    pluginCtxMenu_OpenFile.Tag = new Uri(p.Uri, Plugin.PluginFileName).AbsoluteUri;
                }
                pluginCtxMenu_OpenByExplorer.Tag = localpath;
            } catch (Exception ex) {
                Debug.WriteLine(ex.Message);
                Debug.WriteLine(ex.StackTrace);
            }
        }


	}
}
