using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq.Mapping;
using System.Data.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Mvc.Ajax;
using System.Web.UI;


namespace Spencer
{
    public static class GridViewHelper
    {
        public static string GridView<T>(this HtmlHelper helper)
        {
            return GridView<T>(helper, null, null,new GridViewOption());
        }

        public static string GridView<T>(this HtmlHelper helper, object data)
        {
            return GridView<T>(helper, data, null,new GridViewOption());
        }

        public static string GridView<T>(this HtmlHelper helper, object data, string[] columns, GridViewOption options)
        {
      
            // Get items   
            var items = (IEnumerable<T>)data;
            if (items == null)
                items = (IEnumerable<T>)helper.ViewData.Model;  

            // Get column names   
            if (columns == null)
                columns = typeof(T).GetProperties().Select(p => p.Name).ToArray();

            // Create HtmlTextWriter   
            var writer = new HtmlTextWriter(new StringWriter());

            // Open table tag   
            writer.RenderBeginTag(HtmlTextWriterTag.Table);

            // Render table header   
            writer.RenderBeginTag(HtmlTextWriterTag.Thead);
            RenderHeader(helper, writer, columns, options);
            writer.RenderEndTag();

            string identityColumnName= ((PagedList<T>)items).IdentityColumnName ;

            // Render table body   
            writer.RenderBeginTag(HtmlTextWriterTag.Tbody);
            foreach (var item in items)
                RenderRow<T>(helper, writer, columns, item, identityColumnName, options);
            writer.RenderEndTag();

           
            RenderPagerRow<T>(helper, writer, (PagedList<T>)items, columns.Count());

            // Close table tag   
            writer.RenderEndTag();

            // Return the string   
            return writer.InnerWriter.ToString();
        }


        private static void RenderHeader(HtmlHelper helper, HtmlTextWriter writer, string[] columns, GridViewOption options)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            int i = 0;

            foreach (var columnName in columns)
            {
                writer.RenderBeginTag(HtmlTextWriterTag.Th);
                var currentAction = (string)helper.ViewContext.RouteData.Values["action"];

                string link=null;
                if (options.Columns == null)
                
                    link = helper.ActionLink(columnName, currentAction, new { sort = columnName });
                
                else
                {
                  
                    link = helper.ActionLink(options.Columns[i], currentAction, new { sort = columnName });
                    i++;
                }
                writer.Write(link);
                writer.RenderEndTag();
              

                
            }
            // Show edit column?
            bool showEditColumn = options.ShowEditButton || options.ShowDeleteButton;

            if (showEditColumn)
            { 
              writer.RenderBeginTag(HtmlTextWriterTag.Th);
              writer.Write(helper.Encode(""));
              writer.RenderEndTag();
            }            
            writer.RenderEndTag();
        }

        private static void RenderRow<T>(HtmlHelper helper, HtmlTextWriter writer, string[] columns, T item ,string identityColumnName, GridViewOption options)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            foreach (var columnName in columns)
            {
                writer.RenderBeginTag(HtmlTextWriterTag.Td);
                var value = typeof(T).GetProperty(columnName).GetValue(item, null) ?? String.Empty;
                writer.Write(helper.Encode(value.ToString()));   
                writer.RenderEndTag();
            }

            // Show edit column?
            bool showEditColumn = options.ShowEditButton || options.ShowDeleteButton;

            if (showEditColumn)
            { 
              var identityVaule = typeof(T).GetProperty(identityColumnName).GetValue(item, null);
              writer.RenderBeginTag(HtmlTextWriterTag.Td);

                if ( options.ShowEditButton)
                {
                   var link = helper.ActionLink(options.EditButtonText,options.EditAction , new { id =identityVaule });
                   writer.Write(link);
                   writer.Write(" ");  
                }

                if (options.ShowDeleteButton )
                { 
                   var link = helper.ActionLink(options.DeleteButtonText, options.DeleteAction ,
                                    new { id = identityVaule}, new { OnClick = "return confirm('ب·بدة¾³‎?');" });
                   writer.Write(link);            
                }
                
              writer.RenderEndTag();
            }

            writer.RenderEndTag();
        }

        private static void RenderPagerRow<T>(HtmlHelper helper, HtmlTextWriter writer, PagedList<T> items, int columnCount)
        {
            int nrOfPagesToDisplay = 10;

            // Don't show paging UI for only 1 page   
            if (items.TotalPageCount == 1)
                return;

            // Render page numbers   
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.AddAttribute(HtmlTextWriterAttribute.Colspan, columnCount.ToString());
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            var currentAction = (string)helper.ViewContext.RouteData.Values["action"];

            if (items.PageIndex >= 1)
            {
                var linkText = String.Format("{0}", "<<<");
                var link = helper.ActionLink(linkText, currentAction, new { page = items.PageIndex, sort = items.SortExpression });
                writer.Write(link + "&nbsp;");
            }

            int start = 0;
            int end = items.TotalPageCount;

            if (items.TotalPageCount > nrOfPagesToDisplay)
            {
                int middle = (int)Math.Ceiling(nrOfPagesToDisplay / 2d) - 1;
                int below = (items.PageIndex - middle);
                int above = (items.PageIndex + middle);

                if (below < 4)
                {
                    above = nrOfPagesToDisplay;
                    below = 0;
                }
                else if (above > (items.TotalPageCount - 4))
                {
                    above = items.TotalPageCount;
                    below = (items.TotalPageCount - nrOfPagesToDisplay);
                }

                start = below;
                end = above;
            }

            if (start > 3)
            {
                var linkText = String.Format("{0}", "1");
                var link = helper.ActionLink(linkText, currentAction, new { page = 1, sort = items.SortExpression });
                writer.Write(link + "&nbsp;");

                linkText = String.Format("{0}", "2");
                link = helper.ActionLink(linkText, currentAction, new { page = 2, sort = items.SortExpression });
                writer.Write(link + "&nbsp;");

                writer.Write(String.Format("{0}", "..."));
            }

            for (var i = start; i < end; i++)
            {

                if (i == items.PageIndex)
                {
                    writer.Write(String.Format("<strong>{0}</strong>&nbsp;", i + 1));
                }
                else
                {
                    var linkText = String.Format("{0}", i + 1);
                    var link = helper.ActionLink(linkText, currentAction, new { page = i + 1, sort = items.SortExpression });
                    writer.Write(link + "&nbsp;");
                }

            }

            if (end < (items.TotalPageCount - 3))
            {
                writer.Write(String.Format("{0}", "..."));

                var linkText = String.Format("{0}", items.TotalPageCount - 1);
                var link = helper.ActionLink(linkText, currentAction, new { page = items.TotalPageCount - 1, sort = items.SortExpression });
                writer.Write(link + "&nbsp;");

                linkText = String.Format("{0}", items.TotalPageCount);
                link = helper.ActionLink(linkText, currentAction, new { page = items.TotalPageCount, sort = items.SortExpression });
                writer.Write(link + "&nbsp;");
            }


            if (items.PageIndex + 2 <= items.TotalPageCount)
            {

                var linkText = String.Format("{0}", ">>>");
                var link = helper.ActionLink(linkText, currentAction, new { page = items.PageIndex + 2, sort = items.SortExpression });
                writer.Write(link + "&nbsp;");
            }

            writer.RenderEndTag();
            writer.RenderEndTag();
        }

    }

}
