using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.Design.WebControls;
using System.Web.UI.WebControls;

[assembly: TagPrefix("EasyTabs", "Tabs")]
namespace EasyTabParts
{
    [
      ToolboxData("<{0}:TabList ID='TabListID' runat=\"server\"></{0}:TabList>")
    ]
    public class TabList : ListControl, INamingContainer
    {
        #region Members and Properties

        // Tab Theme - options for tab colors, etc.
        public enum TabThemeOption
        {
            gray,
            blue,
            black,
            gold
        }
        private TabThemeOption _tabTheme = TabThemeOption.gray;
        public TabThemeOption TabTheme
        {
            get { return _tabTheme; }
            set { _tabTheme = value; }
        }

        private Orientation _tabOrientation 
                                = Orientation.Horizontal;
        public Orientation TabOrientation
        {
            get { return _tabOrientation; }
            set { _tabOrientation = value; }
        }

        // Tab Colors Reversed
        private bool _tabColorsReversed = false;
        public bool TabColorsReversed
        {
            get { return _tabColorsReversed; }
            set { _tabColorsReversed = value; }
        }

        // Tab Style - options for tab appearance
        // (reserved for future use ...)
        private enum TabStyleOptions
        {
            embossed,
            flat
        }
        private TabStyleOptions _tabStyle = TabStyleOptions.embossed;
        private TabStyleOptions TabStyle
        {
            get { return _tabStyle; }
            set { _tabStyle = value; }
        }

        private int _fontSize = 10;
        public int FontSize
        {
            get { return _fontSize; }
            set { _fontSize = value; }
        }

        private bool _bold = false;
        public bool Bold
        {
            get { return _bold; }
            set { _bold = value; }
        }

        #endregion

        #region Control Creation and Data Binding

        protected override void CreateChildControls()
        {
            // Create tab controls for items in view state, or items that have been 
            // added via the ListItemCollection API
            CreateTabControls();
        }

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

            // Create tab controls for data bound items
            CreateTabControls();
        }

        // CreateTabControls
        // Creates a "Tab", in the form of a LinkButton control, for each ListItem 
        // in our Items collection, and adds the LinkButtons to our Controls collection
        private void CreateTabControls()
        {
            int i = 0;
            foreach (ListItem li in this.Items)
            {
                LinkButton lb = new LinkButton();
                lb.ID = i++.ToString();         // Elsewhere in this class, the code expects the ID to be a
                                                // string representation of the tab's item index
                lb.Text = li.Text;
                lb.Font.Size = FontUnit.Point(_fontSize);
                lb.Font.Bold = _bold;
                lb.Click += new EventHandler(tab_Click);
                this.Controls.Add(lb);
            }
        }

        #endregion

        #region Rendering
        // Render
        // The strategy is to wrap the LinkButton controls in our Controls collection
        // with addition HTML to make it look like a tabs list. Most of the heavy lifting
        // is in the CSS file ... the markup is simple:
        //
        //  <div class="easyTabs">
        //    <table border="0" cellpadding="0" cellspacing="0">
        //      <tr>
        //        <td>
        //          <ul>
        //            <li><!-- LinkButton 0 Renders HERE --></li>
        //            <li class="selected"><!-- LinkButton 1 Renders HERE --></li>
        //            <li><!-- LinkButton 2 Renders HERE --></li>
        //            <li><!-- LinkButton 3 Renders HERE --></li>
        //          </ul>
        //        </td>
        //      </tr><tr>           <!-- THIS LINE ONLY IF HORIZONTAL -->
        //        <td class="underline">
        //          &nbsp;
        //        </td>
        //      </tr>
        //    </table>
        //  </div>

        protected override void Render(HtmlTextWriter writer)
        {
            // Render opening div with class selector for tab look and feel
            writer.Write("<div class=\"" + GetTabCssClassName() + "\">");

            // Render a table and a table cell for the tab list. The tab list itself is a <ul> element.
            writer.Write("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td><ul>");

            if (this.DesignMode)
            {
                // We are in design mode, so just throw in some sample tabs
                writer.Write(
                    "<li><a>Tab 1</a></li>" +
                    "<li class=\"selected\"><a>Tab 2</a></li>" +
                    "<li><a>Tab 3</a></li>" +
                    "<li><a>Tab 4</a></li>"
                    );
            }
            else
            {
                // We are not in design mode, this is the real deal!
                // Render each LinkButton within <li> ... </li> tags,
                // with a special css class for the selected item
                foreach (Control c in this.Controls)
                {
                    if (c is LinkButton)
                    {
                        // We know the control's ID is the item index, so check to see if we're rendering the 
                        // selected index and decorate the control accordingly
                        int controlIndex = Convert.ToInt32(c.ID);
                        if (controlIndex == this.SelectedIndex)
                        {
                            writer.Write("<li class=\"selected\">");
                        }
                        else
                        {
                            writer.Write("<li>");
                        }
                        c.RenderControl(writer);
                        writer.Write("</li>");
                    }
                }
            }

            // Close up the unnumbered list and table row
            writer.Write("</ul></td>");

            // If we are in horizontal mode, then spawn a new row for the footer
            if (_tabOrientation == Orientation.Horizontal)
            {
                writer.Write("</tr><tr>");
            }

            // Add a row for a splash of color underneath the tabs, then close the table and div
            writer.Write("<td class=\"underline\">&nbsp;&nbsp;&nbsp;&nbsp;</td></tr></table></div>");
        }

        // GetTabCssClassName - Logic for translating control state into the css class
        private string GetTabCssClassName()
        {
            string suffix = "";
            if (_tabColorsReversed)
            {
                suffix = "_r";
            }
            if (_tabOrientation == Orientation.Vertical)
            {
                suffix += "_v";
            }
            return (
                _tabTheme.ToString() + "_" +
                _tabStyle.ToString() + "_tabs" +
                suffix
            );
        }

        #endregion

        #region Event Handlers

        // lb_Click - Someone clicked a tab LinkButton
        private void tab_Click(object sender, EventArgs e)
        {
            if (sender is LinkButton)
            {
                LinkButton lb = sender as LinkButton;
                int oldIndex = this.SelectedIndex;
                int newIndex = Convert.ToInt32(lb.ID);

                // If the user clicked a new index, then update the selected item
                // and fire our SelectedIndexChanged event
                if (oldIndex != newIndex)
                {
                    if (oldIndex >= 0)
                    {
                        this.Items[oldIndex].Selected = false;
                    }
                    this.Items[newIndex].Selected = true;

                    OnSelectedIndexChanged(e);
                }
            }
        }

        #endregion

    }
}
