/***************************************************
 * This code is Copyright 2008 Michael J. Ellison.  All rights reserved.
 * Usage and distribution of this code is governed by the
 * CodeProject Open License.  A copy of the license may be found
 * at:
 * http://www.codeproject.com/info/cpol10.aspx
 * **************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.Design.WebControls;
using System.ComponentModel.Design;
using System.ComponentModel;
using System.Text.RegularExpressions;



namespace UNLV.IAP.WebControls
{ 
    /// <summary>
    /// Provides design-time support for a <see cref="GroupingView"/> control.
    /// </summary>
    public class GroupingViewDesigner : DataBoundControlDesigner
    {

        private TemplateGroupCollection _templates = null;

        /// <summary>
        /// Gets a value that identifies whether or not a <see cref="GroupingView.GroupTemplate">GroupTemplate</see>
        /// has been defined in the designed control.
        /// </summary>
        protected bool GroupTemplateExists
        {
            get
            {
                return (ComponentControl.GroupTemplate != null);
            }
        }

        /// <summary>
        /// Gets the designed component typed as a <see cref="GroupingView"/> control.
        /// </summary>
        public GroupingView ComponentControl
        {
            get { return (Component as GroupingView); }
        }

        /// <summary>
        /// Gets or sets the <see cref="GroupingView.GroupingDataField">GroupingDataField</see>
        /// property value of the desgined <see cref="GroupingView" /> control.
        /// </summary>
        public string GroupingDataField
        {
            get { return ComponentControl.GroupingDataField; }
            set { ComponentControl.GroupingDataField = value; }
        }

        /// <summary>
        /// Gets or sets the <see cref="GroupingView.AutobindDataSourceChildren">AutobindDataSourceChildren</see>
        /// property value of the desgined <see cref="GroupingView" /> control.
        /// </summary>
        public bool AutobindDataSourceChildren
        {
            get { return ComponentControl.AutobindDataSourceChildren; }
            set { ComponentControl.AutobindDataSourceChildren = value; }
        }

        /// <summary>
        /// Initializes the designer.
        /// </summary>
        /// <param name="component">The <see cref="GroupingView" /> component to design.</param>
        public override void Initialize(System.ComponentModel.IComponent component)
        {
            base.Initialize(component);
            if (!(component is GroupingView))
                throw new ArgumentException("Component must be a GroupingView to use a GroupingViewDesigner");
            else
                SetViewFlags(ViewFlags.TemplateEditing, true);
        }

        /// <summary>
        /// Gets the collection of templates supported for editing in the designer.
        /// </summary>
        public override TemplateGroupCollection TemplateGroups
        {
            get
            {
                if (_templates == null)
                {
                    // get the base collection
                    _templates = base.TemplateGroups;

                    GroupingView ctl = Component as GroupingView;

                    // templates for Group and Item
                    TemplateDefinition groupDef = new TemplateDefinition(this, "GroupTemplate", ctl, "GroupTemplate", false);
                    TemplateDefinition itemDef = new TemplateDefinition(this, "ItemTemplate", ctl, "ItemTemplate", false);
                    TemplateDefinition groupSepDef = new TemplateDefinition(this, "GroupSeparatorTemplate", ctl, "GroupSeparatorTemplate", false);
                    TemplateDefinition itemSepDef = new TemplateDefinition(this, "ItemSeparatorTemplate", ctl, "ItemSeparatorTemplate", false);
                    TemplateDefinition emptyDef = new TemplateDefinition(this, "EmptyDataTemplate", ctl, "EmptyDataTemplate", false);

                    // create a template group
                    TemplateGroup tg = new TemplateGroup("GroupingView Templates");
                    tg.AddTemplateDefinition(groupDef);
                    tg.AddTemplateDefinition(itemDef);
                    tg.AddTemplateDefinition(groupSepDef);
                    tg.AddTemplateDefinition(itemSepDef);
                    tg.AddTemplateDefinition(emptyDef);

                    // add the group to the groupcollection
                    _templates.Add(tg);
                }

                return _templates;
            }
        }

        /// <summary>
        /// Gets the collection of action lists supported in the designer.
        /// </summary>
        public override System.ComponentModel.Design.DesignerActionListCollection ActionLists
        {
            get
            {
                DesignerActionListCollection col = base.ActionLists;
                col.Add(new GroupingViewDesignerActionList(this));
                return col;
            }
        }

        /// <summary>
        /// Returns the html markup that provides the representation of a 
        /// <see cref="GroupingView" /> control in a design-time environment.
        /// </summary>
        /// <returns></returns>
        public override string GetDesignTimeHtml()
        {
            string html = "";
            if (GroupTemplateExists)
            {
                html = base.GetDesignTimeHtml();
                // if the html is an empty tag, return an empty placeholder instead
                if (IsEmptyTag(html))
                    html = GetEmptyDesignTimeHtml();
                
            }
            else
                html = CreatePlaceHolderDesignTimeHtml("Switch to Source view to edit the GroupTemplate.<br />The ItemTemplate is optional.");

            return html; 
        }

        /// <summary>
        /// Returns <c>true</c> if the given html is an empty tag, <c>false</c> if not.
        /// </summary>
        /// <param name="html">The html to inspect.</param>
        /// <returns>Whether the html is an empty tag.</returns>
        protected bool IsEmptyTag(string html)
        {
            Regex r = new Regex(@"^<(.*)>\s*</(.*)>$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
            return (r.IsMatch(html));
        }


        /// <summary>
        /// Assigns the DataFieldConverter type converter to the GroupingDataField property.
        /// </summary>
        /// <param name="properties">The properties to filter.</param>
        protected override void PreFilterProperties(IDictionary properties)
        {

            base.PreFilterProperties(properties);
            Attribute[] attributes = new Attribute[] { new TypeConverterAttribute(typeof(DataFieldConverter)) };
            PropertyDescriptor oldPropertyDescriptor = (PropertyDescriptor)properties["GroupingDataField"];
            oldPropertyDescriptor = TypeDescriptor.CreateProperty(this.GetType(), oldPropertyDescriptor, attributes);
            properties["GroupingDataField"] = oldPropertyDescriptor;

        }


    }
}
