using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Linq;

namespace FinancialChartExplorer.Models
{
    public static class ControlPages
    {
        private static List<ControlPageGroup> _pageGroups;
        private static List<ControlPage> _pages;
        private static IDictionary<string, ControlPage> _pageDic;
        private const string PagesFileInServer = "~/Content/ControlPages.xml";
        private static readonly object _locker = new object();

        public static IDictionary<string, string> GetPageSources(string controllerName, string actionName)
        {
            var pageSources = new Dictionary<string, string>();

            var controllerFileName = actionName + "Controller.cs";
            var controllerFilePath = HttpContext.Current.Server.MapPath(
                string.Format("~/Controllers/{0}/{1}", controllerName, controllerFileName));
            var controllerFileHtml = GetFileAsHtmlContent(controllerFilePath);
            pageSources.Add(controllerFileName, controllerFileHtml);

            var viewFileName = actionName + ".cshtml";
            var viewFilePath = HttpContext.Current.Server.MapPath(
                string.Format("~/Views/{0}/{1}", controllerName, viewFileName));
            var viewFileHtml = GetFileAsHtmlContent(viewFilePath);
            pageSources.Add(viewFileName, viewFileHtml);

            return pageSources;
        }

        public static ControlPageGroup GetControlPageGroup(string groupName)
        {
            EnsurePages();
            return _pageGroups.FirstOrDefault(pageGroup => pageGroup.GroupName.ToLower() == groupName.ToLower());
        }

        public static List<ControlPageGroup> getPageGroups()
        {
            EnsurePages();
            return _pageGroups;
        }

        private static string GetFileAsHtmlContent(string controllerFilePath)
        {
            return System.IO.File.ReadAllText(controllerFilePath);
        }

        public static string GetPageText(string actionName)
        {
            EnsurePages();
            return _pageDic.ContainsKey(actionName) ? _pageDic[actionName].Text : "OverView";
        }

        public static IEnumerable<ControlPage> Pages
        {
            get
            {
                EnsurePages();
                return _pages;
            }
        }

        private static void EnsurePages()
        {
            if (_pages != null)
            {
                return;
            }

            lock (_locker)
            {
                if (_pages != null)
                {
                    return;
                }

                var root = XElement.Load(HttpContext.Current.Server.MapPath(PagesFileInServer));
                _pages = new List<ControlPage>();
                _pageGroups = new List<ControlPageGroup>();
                foreach (var groupElement in root.Elements("Group"))
                {
                    var pageGroups = new List<ControlPageGroup>();
                    var currentGroup = groupElement.Attribute("name").Value;
                    var docElement = root.Attribute("documentation");
                    var documentation = docElement == null ? null : docElement.Value;
                    var pages = GetControlPagesFromXEle(groupElement, currentGroup);
                    _pages.AddRange(pages);
                    pageGroups.Add(new ControlPageGroup
                    {
                        GroupName = currentGroup,
                        Documentation = documentation,
                        Pages = pages
                    });
                    _pageGroups.AddRange(pageGroups);
                }
                _pageDic = new Dictionary<string, ControlPage>(StringComparer.OrdinalIgnoreCase);
                foreach (var page in Pages)
                {
                    _pageDic.Add(page.Name, page);
                }
            }
        }

        private static List<ControlPage> GetControlPagesFromXEle(XElement controlElement, string groupName)
        {
            var pages = controlElement.Elements("action").Select(e =>
            {
                ControlPage page = new ControlPage
                {
                    Text = e.Attribute("text").Value,
                    Name = e.Attribute("name").Value,
                    GroupName = groupName
                };
                return page;
            }).ToList();
            return pages;
        }
    }

    public class ControlGroup
    {
        public IEnumerable<ControlPageGroup> controls { get; set; }
        public string GroupName { get; set; }
    }

    public class ControlPageGroup
    {
        private const string DocumentationRoot = "http://helpcentral.componentone.com/nethelp/c1mvchelpers";
        private string _documentation;

        public string Documentation
        {
            get
            {
                if (string.IsNullOrEmpty(_documentation))
                {
                    return DocumentationRoot;
                }

                return _documentation;
            }
            set { _documentation = value; }
        }

        public IEnumerable<ControlPage> Pages { get; set; }
        public string GroupName { get; set; }
        public int GetSelectedPageIndex(string actionName)
        {
            int sIndex = -1, index = 0;
            foreach (var page in Pages)
            {
                if (page.Name.ToLower() == actionName.ToLower())
                    return index;
                index++;
            }
            return sIndex;
        }
    }

    public class ControlPage
    {
        public string Name { get; set; }
        public string Text { get; set; }
        public string Path { get; set; }
        public string GroupName { get; set; }
    }
}