//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using CommunityServer.Components;
using CommunityServer.ControlPanel.UI;
using CA = ComponentArt.Web.UI;

namespace CommunityServer.ControlPanel.Photos
{
	/// <summary>
	///		Summary description for CategoryChecklistControl.
	/// </summary>
	public class CategoryChecklistControl : BaseGalleryControl
	{

		#region Public Properties

		private ArrayList selectedNodes;
		public virtual ArrayList SelectedNodes
		{
			get
			{
				if(pageHasLoaded)
					return GetSelectedNodes();
				else
				{
					return selectedNodes;
				}
			}
			set
			{
				selectedNodes = value;
				if(pageHasLoaded)
					SetSelectedNodes(value);
			}
		}

		[DefaultValue( "" )]
		public virtual string TreeCommand
		{
			get
			{
				Object state = ViewState["TreeCommand"];
				if(state != null)
					return (string)state;
				return "";
			}
			set { ViewState["TreeCommand"] = value; }
		}

		#endregion

		#region Child Controls

		protected CA.TreeView TreeView1;
		bool pageHasLoaded = false;

		#endregion

		private void Page_Load(object sender, EventArgs e)
		{
			if(!Page.IsPostBack)
			{
				buildTree();
				//TreeView1.SelectedNode = TreeView1.Nodes[(CSContext.Current.CategoryID == -1) ? 0 : CSContext.Current.CategoryID];
				if(SelectedNodes != null)
					SetSelectedNodes(SelectedNodes) ;
			}
			pageHasLoaded = true;
		}

		#region Web Form Designer generated code
		override protected void OnInit(EventArgs e)
		{
			//
			// CODEGEN: This call is required by the ASP.NET Web Form Designer.
			//
			InitializeComponent();
			base.OnInit(e);
		}
		
		/// <summary>
		///		Required method for Designer support - do not modify
		///		the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.Load += new EventHandler(this.Page_Load);

		}
		#endregion

		/// <summary>
		/// Sets the checkmarks on the selected categories.  This needs to be done after the 
		/// Datasource and nodes have been added to the tree.
		/// </summary>
		/// <param name="postCategories"></param>
		private void SetSelectedNodes(ArrayList postCategories)
		{
				foreach(CA.TreeViewNode root  in TreeView1.Nodes)
				{
					//reset all nodes to unchecked
					root.UnCheckAll();

					ProcessNodeForSelected(root,postCategories);

					if(root.Nodes.Count > 0) //recurse
						ProcessNodeForSelectedChildren(root, postCategories);

				}
		}

		/// <summary>
		/// Recurses through the node tree to all leaf nodes from a root, processing them
		/// to see if they should be selected
		/// </summary>
		/// <param name="node"></param>
		/// <param name="postCategories"></param>
		private void ProcessNodeForSelectedChildren(CA.TreeViewNode node, ArrayList postCategories)
		{
			foreach(CA.TreeViewNode child in node.Nodes)
			{
				ProcessNodeForSelected(child,postCategories);
				if(child.Nodes.Count > 0) //recurse
					ProcessNodeForSelectedChildren(child, postCategories);

			}
		}

		/// <summary>
		/// Examines the current node and sets the checkmark state if selected
		/// </summary>
		/// <param name="node"></param>
		/// <param name="postCategories"></param>
		private void ProcessNodeForSelected(CA.TreeViewNode node, ArrayList postCategories)
		{
			//See if the node is in the list to be checked
			foreach(PostCategory pc in postCategories)
			{
				if(node.ID == pc.CategoryID.ToString())
					node.Checked = true;
			}
		}

		/// <summary>
		/// Retrieves the checked members from the treecontrol
		/// </summary>
		/// <returns></returns>
		private ArrayList GetSelectedNodes()
		{
			ArrayList al = new ArrayList();
			foreach(CA.TreeViewNode n in TreeView1.CheckedNodes)
			{
				PostCategory pc = new PostCategory();
				pc.Name = n.Text;
				pc.SectionID = this.CurrentGallery.SectionID;
				pc.CategoryID = Globals.SafeInt(n.ID, -1) ;
				al.Add(pc);
			}
			return al;
		}

		/// <summary>
		/// Sets the the selected nodes based on a single PostCategory
		/// </summary>
		/// <param name="pc"></param>
		public void SetSingleSelectedNode(PostCategory pc)
		{
			if(pc != null)
			{
				ArrayList al = new ArrayList();
				al.Add(pc);
				this.SelectedNodes = al;
			}
		}

		/// <summary>
		/// Sets the the selected nodes based on a single PostCategory ID
		/// </summary>
		/// <param name="categoryID"></param>
		public void SetSingleSelectedNode(int categoryID, int sectionID)
		{
			if(categoryID <= 0)
				return;

			SetSingleSelectedNode(PostCategories.GetCategory(categoryID, sectionID));
		}

		/// <summary>
		/// Returns the CategoryID of the first node selected (-1 if none)
		/// </summary>
		/// <returns></returns>
		public int GetFirstSelectedNodeID()
		{
			foreach (PostCategory pc in this.SelectedNodes)
				return pc.CategoryID; 

			return -1;
		}

		/// <summary>
		/// Returns a string array of the names of the selected nodes
		/// </summary>
		/// <returns></returns>
		public string[] SelectedNodeNames()
		{
			ArrayList al = new ArrayList();
			foreach (PostCategory pc in this.SelectedNodes)
				al.Add(pc.Name);

			return (string[]) al.ToArray(typeof (string));

		}



		private void buildTree()
		{
			ArrayList categories = PostCategories.GetCategories(CurrentGallery.SectionID, false, true, -1);
			PostCategory root = new PostCategory();
			root.Name = "\\";
			root.IsEnabled = true;

			categories.Add(root);

			DataTable dt = CADataConverter.ToDataTable(categories,typeof(PostCategory));

			
			/*if(!dt.Columns.Contains("ParentNodeId"))
				dt.Columns.Add("ParentNodeId", typeof(int));*/
			foreach(DataRow dbRow in dt.Rows)
			{
				if(dbRow["CategoryID"].ToString() == "0")
				{
					dbRow["ParentID"] = DBNull.Value;
				}
			}
			

			DataSet ds = new DataSet();
			ds.Tables.Add(dt);
			ds.Relations.Add("NodeRelation", ds.Tables[0].Columns["CategoryID"], ds.Tables[0].Columns["ParentID"]);

			//Loop through categories to find the root
			foreach(DataRow dbRow in ds.Tables[0].Rows)
			{
				if(dbRow.IsNull("ParentID"))
				{   
					//Write out the root node
					CA.TreeViewNode newNode = CreateNode(dbRow["CategoryID"].ToString(), dbRow["Name"].ToString(), TreeView1.ParentNodeImageUrl , true, false, false);
					TreeView1.Nodes.Add(newNode);
					
					//Pass the root to the tree builder
					PopulateSubTree(dbRow, newNode);
				}
			}
		}

		/// <summary>
		/// Enumerates through the children of a specified root node Adding them to the Tree
		/// </summary>
		/// <param name="dbRow"></param>
		/// <param name="node"></param>
		private void PopulateSubTree(DataRow dbRow, CA.TreeViewNode node)
		{
			foreach (DataRow childRow in dbRow.GetChildRows("NodeRelation"))
			{ 
				//We could add a check here to see if the childRow has children to determine
				//if it is a parent node or leaf node for formatting, if we used different images
				CA.TreeViewNode childNode = CreateNode(childRow["CategoryID"].ToString(), childRow["Name"].ToString(), TreeView1.LeafNodeImageUrl , true, true, false);
				node.Nodes.Add(childNode);
				PopulateSubTree(childRow, childNode);
			}
		}

		/// <summary>
		/// Helper to build a node and set the properties
		/// </summary>
		/// <param name="categoryID"></param>
		/// <param name="text"></param>
		/// <param name="imageurl"></param>
		/// <param name="isExpanded"></param>
		/// <param name="hasCheckmark"></param>
		/// <param name="isChecked"></param>
		/// <returns></returns>
		private CA.TreeViewNode CreateNode(string categoryID, string text, string imageurl, bool isExpanded, bool hasCheckmark, bool isChecked)
		{
			CA.TreeViewNode node = new CA.TreeViewNode();
			node.Text = text; 
			node.ImageUrl = imageurl; 
			node.Expanded = isExpanded;
			node.ShowCheckBox = hasCheckmark;
			node.Checked = isChecked;
			node.ID = categoryID;
			return node;
		}

		public event EventHandler TreeChanged;

		protected void OnPageChange(EventArgs e)
		{
			if(TreeChanged != null)
				TreeChanged(this, e);
		}

	}
}
