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

using System;
using System.Globalization;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.UI;
using System.Xml.Serialization;
using CommunityServer.Components;
//NOTE: This should be refactored into a "real" control. For now, it simply renders the markup for our admin tabs.

namespace CommunityServer.Controls
{

    /// <summary>
    /// Renders a Tab + Submenus based on the tab configuration file.
    /// </summary>
    public class TabControl : Control
    {
        #region Private Members
        private string _selectedTab;
        private string _fileLocation;
        private bool _showChildren = true;
        #endregion

        #region Public Properties
        /// <summary>
        /// Returns the currently selected tab
        /// </summary>
        public virtual string SelectedTab
        {
            get {  return this._selectedTab; }
            set {  this._selectedTab = value; }
        }
        
        /// <summary>
        /// Controls if Child tabs are displayed below the selected parent.
        /// </summary>
        public bool ShowChildren
        {
            get {  return this._showChildren; }
            set {  this._showChildren = value; }
        }

        /// <summary>
        /// returns the location of the current tab configuration file
        /// </summary>
        public virtual string FileLocation
        {
            get 
            {
                if(_fileLocation == null)
                    _fileLocation = "~/admin/tab.config";

                return this._fileLocation; 
            }
            set {  this._fileLocation = value; }
        }
        #endregion

        #region GetTabs()
        /// <summary>
        /// Returns the current instance of the TabCollection
        /// </summary>
        /// <returns></returns>
        protected TabCollection GetTabs()
        {
            string path = FileLocation;

			if(path.StartsWith("/") || path.StartsWith("~"))
				path = Context.Server.MapPath(path);

            TabCollection tc = CSCache.Get(path) as TabCollection;
            if(tc == null)
            {
                
                tc = (TabCollection)Serializer.ConvertFileToObject(path,typeof(TabCollection));
                CSCache.Max(path,tc,new CacheDependency(path));
            }
            return tc;
        }
        #endregion

        #region Tab Helpers


		//NOTE: clean up the filtering

		/// <summary>
		/// Allows tabs to removed/not included on other tabs
		/// </summary>
		protected bool IsNotFiltered(Tab child)
		{
			if(child.Filter == null)
				return true;
           
	
				string[] filters = child.Filter.Split(',');
				foreach(string filter in filters)
				{
					if(string.Compare(filter,this.SelectedTab,true)==0)
						return false;
				}
	
			return true;

		}
		
		/// <summary>
        /// Checks to see if the current tab has an Roles and if the current user is a member any
        /// of the roles
        /// </summary>
        protected bool IncludeLink(Tab t)
        {
            if(t.HasRoles)
            {
                string[] roles = t.Roles.Split(';');
                foreach(string role in roles)
                {
                    if(Context.User.IsInRole(role))
                        return true;
                }
                return false;
            }
            return true;
        }

        /// <summary>
        /// Resolves the current url and attempts to append the specified querystring
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        protected string FormatLink(Tab t)
        {
			string url = null;
			
			if(t.UrlName==null)
			{
				if(!t.HasHref)
					return Context.Request.Url.ToString();


				if(t.HasQueryString)
					url = string.Format(t.Href.Replace('^','&'),Context.Request.QueryString[t.QueryString]);
				else
					url = t.Href;

			}
			else
			{
				if(!t.HasParameters)
					url = RegisterSelectedTab(t,FormatUrl(t.UrlName));
				else
					url = RegisterSelectedTab(t,FormatUrl(t.UrlName,t.UrlParameters));
			}

			return ResolveUrl(url);
        }

		protected string FormatUrl(string name)
		{
			return Globals.GetSiteUrls().UrlData.FormatUrl(name);
		}

		protected string FormatUrl(string name, params object[] parameters)
		{
			return Globals.GetSiteUrls().UrlData.FormatUrl(name, parameters);
		}

		protected string RegisterSelectedTab(Tab t, string url )
		{
			if(url.ToLower().IndexOf("tab=") > 0 )
				return url;
			
			if(url.IndexOf('?') < 0 )
				return string.Concat(url, "?tab=", t.Name);
			else
				return string.Concat(url, "&tab=", t.Name);
		}


		protected virtual string GetText(Tab t)
		{
			if(t.HasText)
				return t.Text;
			else
				return ResourceManager.GetString(t.ResourceName); 
		}
        #endregion

        #region GetState
        /// <summary>
        /// Walks the tab and it's children to see if any of them are currently selected
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        private SelectedState GetState(Tab t)
        {
            //Check the parent
            if(string.Compare(t.Name,SelectedTab,true,CultureInfo.InvariantCulture) == 0)
                return SelectedState.Parent;

            //Walk each of the child tabs
            if(t.HasChildren)
            {
                foreach(Tab child in t.Children)
                {
                    if(string.Compare(child.Name,this.SelectedTab,true,CultureInfo.InvariantCulture) == 0)
                        return SelectedState.Child;
                    else if(child.HasChildren)
                    {
                        foreach(Tab cc in child.Children)
                            if(string.Compare(cc.Name,this.SelectedTab,true,CultureInfo.InvariantCulture) == 0)
                                return SelectedState.ChildChild;
                    }
                }
            }

            //Nothing here is selected
            return SelectedState.Not;
   
        }
        #endregion

        #region CreateTabMarkUp
        /// <summary>
        /// Creates the markup for the current TabCollection
        /// </summary>
        /// <returns></returns>
        protected string CreateTabMarkUp()
        {
            //Get the tab data
            TabCollection tc = GetTabs();

            
        	StringBuilder sb = new StringBuilder();
            
            //Open the primary UL
            sb.Append("<ul id=\"primary\">");

            //Walk the parents
            foreach(Tab parent in tc.Tabs)
            {
                //Is this parent enabled? Check Permissions
                if(parent.IsValid(Context))
                {
                    //Check to see if/how this is tab is selected
                    SelectedState state = GetState(parent);
                    if(state == SelectedState.Not)
                    {
                        //Not selected, just render a normal link
                        sb.AppendFormat("<li><a href=\"{0}\">{1}</a></li>",FormatLink(parent),GetText(parent));
                    }
                    else
                    {
                        //Something here is selected

                        //Parent is rendered in normal span tags.
                        sb.AppendFormat("<li><a class=\"selectedtab\" href=\"{0}\">{1}</a>",FormatLink(parent),GetText(parent));

                        //Is there any child tabs? Do we want to display them?
                        if(this.ShowChildren && parent.HasChildren)
                        {
                            //Start child UL
                            sb.Append("<ul id=\"secondary\">");
                            
                            foreach(Tab child in parent.Children)
                            {
                                //Make sure this tab is OK to display
                                if(child.Enabled && IncludeLink(child) && IsNotFiltered(child))
                                {
                                    //open li
                                    sb.Append("<li>");

                                    //if the parent is selected, we dispaly links to all child tabs
//                                    if(state == SelectedState.Parent || string.Compare(child.Name,this.SelectedTab,true,CultureInfo.InvariantCulture) != 0)
//                                    {
                                        sb.AppendFormat("<a href=\"{0}\">{1}</a>",FormatLink(child),GetText(child));
//                                    }
//                                    else
//                                    {
//                                        //This child tab is selected, do not display a link
//                                        sb.AppendFormat("<span>{0}</span>",child.Text);
//                                    }
                                    //close li
                                    sb.Append("</li>");
                                }
                            }

                            //close secondary UL
                              sb.Append("</ul>");

                          
                        }
                    }
                }
            }
            sb.Append("</ul>");


        	BuildBreadCrumb(sb, tc);

        	//return results
            return sb.ToString();
        }

    	protected virtual void BuildBreadCrumb(StringBuilder sb, TabCollection tc)
    	{
    		sb.Append("<div id=\"bread\">");
	
    		foreach(Tab parent in tc.Tabs)
    		{
    			//Is this parent enabled? Check Permissions
    			if(parent.Enabled && IncludeLink(parent))
    			{
    				SelectedState state = GetState(parent);
    				if(state == SelectedState.Not)
    				{
    					if(parent.IsRoot)
    						sb.AppendFormat("You are here: <a href=\"{0}\">{1}</a>  ",FormatLink(parent),parent.Text);
    				}
    				else if(state == SelectedState.Parent && !parent.IsRoot)
    					sb.AppendFormat("<a href=\"{0}\">{1}</a> ",FormatLink(parent), parent.Text);
    				else if(state == SelectedState.Child)
    				{
    					sb.AppendFormat("<a href=\"{0}\">{1}</a>  ",FormatLink(parent),parent.Text);
    					if(parent.HasChildren)
    					{
    						foreach(Tab child in parent.Children)
    						{
    							if(string.Compare(child.Name,this.SelectedTab,true,CultureInfo.InvariantCulture) == 0)
    							{
    								sb.AppendFormat("<a href=\"{0}\">{1}</a>",FormatLink(child),child.Text);
    							}
    						}
    					}

    				}
    				else if(state == SelectedState.ChildChild)
    				{
    					foreach(Tab child in parent.Children)
    					{
    						if(child.HasChildren)
    						{
    							foreach(Tab cc in child.Children)
    							{
    								if(string.Compare(cc.Name,this.SelectedTab,true,CultureInfo.InvariantCulture) == 0)
    								{
    									sb.AppendFormat("<a href=\"{0}\">{1}</a> >> ",FormatLink(parent),parent.Text);
    									sb.AppendFormat("<a href=\"{0}\">{1}</a> >> ",FormatLink(child),child.Text);
    									sb.AppendFormat("<a href=\"{0}\">{1}</a>",FormatLink(cc),cc.Text);
    								}
    							}
    						}
    					}
    				}
    			}
    		}
	
	
	
    		sb.Append("</div>");
    	}

    	#endregion

        #region Render
        /// <summary>
        /// Renders the Html representing the Tab control
        /// </summary>
        /// <param name="writer"></param>
        protected override void Render(HtmlTextWriter writer)
        {
            #if DEBUG
                    writer.WriteLine("<!--Tab Control Start -->");
            #endif
            
            string output = ViewState["Tabs"] as String;
            if(output == null)
            {                
                output = CreateTabMarkUp();
                ViewState["Tabs"] = output;

            }
            writer.WriteLine(output);

            #if DEBUG
                    writer.WriteLine("<!--Tab Control End -->");
            #endif


        }
        #endregion

        #region SelectedState
        /// <summary>
        /// Internal enum used to track if a tab is selected
        /// </summary>
        protected enum SelectedState
        {
            Not,
            Parent,
            Child,
            ChildChild
        };
        #endregion

    }
}
