using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Hosting;

namespace ynhtm.Theme
{
    using Common;
    using DBUtility;
    using Theme.Configuration;

    class RewriteItem
    {
        const string URLPAR = " IN (@Url1,@Url2,@Url3)";

        public RewriteItem(int type, int keyID)
        {
            this.Type = type;
            this.KeyID = keyID;
        }

        public int Type { get; private set; }
        public int KeyID { get; private set; }

        public static RewriteItem GetRewrite(string url)
        {
            using (var db = DbBase.GetDb())
            {
                var s = url.TrimEnd('/');
                using (var reader = db.ExecuteReader("SELECT " + DAL.Category.CATEGORYID + " AS KeyID, 1 AS Type FROM " + DAL.Category.SQL_TABLE + " WHERE " + DAL.Category.REWRITE + URLPAR + " UNION SELECT " + DAL.Post.POSTID + " AS KeyID, 2 AS Type FROM " + DAL.Post.SQL_TABLE + " WHERE " + DAL.Post.REWRITE + URLPAR + " AND " + DAL.Post.ENABLED + " = 1 UNION SELECT " + DAL.Job.JOBID + " AS KeyID, 3 AS Type FROM " + DAL.Job.SQL_TABLE + " WHERE " + DAL.Job.REWRITE + URLPAR + " AND " + DAL.Job.ENABLED + " = 1", db.CreateParameter("Url1", url), db.CreateParameter("Url2", s), db.CreateParameter("Url3", s + "/")))
                {
                    if (!reader.Read()) return null;
                    return new RewriteItem
                    (
                        reader.GetInt32("Type"),
                        reader.GetInt32("KeyID")
                    );
                }
            }
        }
    }

    class Process
    {
        public virtual void RemapHandler(HttpApplication context, IHandler handler, string fileName)
        {
            var setting = new BLL.Setting();
            var settingItem = setting.Get();
            var theme = HostingEnvironment.MapPath("~/Theme/" + settingItem.Theme.IifNullOrWhiteSpace("Default") + "/");
            var path = theme + fileName;
            if (!File.Exists(path)) path = Path.ChangeExtension(path, "vbhtml");
            handler.FileName = path;
            context.Context.RemapHandler(handler);
        }

        public virtual void Category(HttpApplication context, Model.Category item)
        {
            if (item.HomeTheme.IsNullOrWhiteSpace() || Parser.LISTPROVIDER.IsPageUrl(context.Request.RawUrl))
                this.RemapHandler(context, new Handler<Template.Category.TemplateList, Model.Category>(item), item.ListTheme.IifNullOrWhiteSpace("List.cshtml"));
            else
                this.RemapHandler(context, new Handler<Template.Category.TemplateHome, Model.Category>(item), item.HomeTheme);
        }

        public virtual void Post(HttpApplication context, Model.Post item)
        {
            var fileName = item.Theme.IifNullOrWhiteSpace("Post.cshtml");
            if (item.CategoryID != null)
            {
                var category = new BLL.Category();
                var categoryItem = category.GetByCategoryID((int)item.CategoryID);
                if (categoryItem != null && !categoryItem.PostTheme.IsNullOrWhiteSpace()) fileName = categoryItem.PostTheme;
            }
            this.RemapHandler(context, new Handler<Template.Post.Template, Model.Post>(item), fileName);
        }

        public virtual void Comment(HttpApplication context, Model.Post item)
        {
            this.RemapHandler(context, new Handler<Template.Post.Comment, Model.Post>(item), "Comment.cshtml");
        }

        public virtual void Job(HttpApplication context, Model.Job item)
        {
            this.RemapHandler(context, new Handler<Template.Job.Template, Model.Job>(item), "Job.cshtml");
        }

        public virtual void JobTry(HttpApplication context, Model.Job item)
        {
            this.RemapHandler(context, new Handler<Template.Job.Template, Model.Job>(item), item.Theme.IifNullOrWhiteSpace("JobTry.cshtml"));
        }

        public virtual void JobList(HttpApplication context)
        {
            this.RemapHandler(context, new Handler<Template.Job.TemplateList>(), "JobList.cshtml");
        }

        public virtual bool Rewrite(HttpApplication context, string url)
        {
            var item = RewriteItem.GetRewrite(url);
            if (item != null)
            {
                var category = new BLL.Category();
                var post = new BLL.Post();
                var job = new BLL.Job();
                switch (item.Type)
                {
                    case 1:
                        var categoryItem = category.GetByCategoryID(item.KeyID);
                        this.Category(context, categoryItem);
                        return true;
                    case 2:
                        var postItem = post.GetByPostID(item.KeyID);
                        if (postItem.Enabled) this.Post(context, postItem);
                        return true;
                    case 3:
                        var jobItem = job.GetByJobID(item.KeyID);
                        if (jobItem.Enabled) this.Job(context, jobItem);
                        return true;
                }
            }
            return false;
        }

        public virtual UrlElementCollection Urls
        {
            get { return Parser.CONFIG != null ? Parser.CONFIG.Urls : null; }
        }

        bool Remap(HttpApplication context, string url)
        {
            var category = new BLL.Category();
            var post = new BLL.Post();
            var job = new BLL.Job();
            if (url == "/" || url == "")
            {
                this.RemapHandler(context, new Handler<Template.TemplateBase>(), "Default.cshtml");
                return true;
            }
            var macth = Regex.Match(url, @"^/Category/(\d+)/?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            if (macth.Success)
            {
                var categoryItem = category.GetByCategoryID(int.Parse(macth.Result("$1")));
                this.Category(context, categoryItem);
                return true;
            }
            macth = Regex.Match(url, @"^/(\d+)/?$", RegexOptions.Compiled);
            if (macth.Success)
            {
                var postItem = post.GetByPostID(int.Parse(macth.Result("$1")));
                if (postItem.Enabled) this.Post(context, postItem);
                return true;
            }
            macth = Regex.Match(url, @"^/(\d+)/Comment/?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            if (macth.Success)
            {
                var postItem = post.GetByPostID(int.Parse(macth.Result("$1")));
                if (postItem.Enabled && postItem.CommentEnabled) this.Comment(context, postItem);
                return true;
            }
            macth = Regex.Match(url, @"^/Job/?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            if (macth.Success)
            {
                this.JobList(context);
                return true;
            }
            macth = Regex.Match(url, @"^/Job/(\d+)/?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            if (macth.Success)
            {
                var jobItem = job.GetByJobID(int.Parse(macth.Result("$1")));
                if (jobItem.Enabled) this.Job(context, jobItem);
                return true;
            }
            macth = Regex.Match(url, @"^/Job/(\d+)/Try/?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            if (macth.Success)
            {
                var jobItem = job.GetByJobID(int.Parse(macth.Result("$1")));
                if (jobItem.Enabled) this.JobTry(context, jobItem);
                return true;
            }
            return false;
        }

        public virtual void Init(HttpApplication context)
        {
            var request = context.Request;
            //分析URL
            var url = Parser.LISTPROVIDER.GetSourceUrl(request.Path).TrimEnd('/', '\\');
            //调用解析
            if (this.Remap(context, url)) return;
            //数据库映射
            if (this.Rewrite(context, url)) return;
            //配置文件映射
            var urls = this.Urls;
            if (urls != null)
            {
                foreach (UrlElement i in urls)
                {
                    if (string.Equals(url, i.Url.TrimEnd('/', '\\'), StringComparison.OrdinalIgnoreCase) || (i.Regex && Regex.IsMatch(url, i.Url.TrimEnd('/', '\\'), RegexOptions.IgnoreCase | RegexOptions.Compiled)))
                    {
                        if (!i.File.IsNullOrWhiteSpace())
                            this.RemapHandler(context, new Handler<Template.TemplateBase>(), i.File);
                        else
                            this.Remap(context, i.Rewrite);
                        return;
                    }
                }
            }
        }
    }

    class ProcessWap : Process
    {
        class Home : IHttpHandler
        {
            public void ProcessRequest(HttpContext context)
            {
                var setting = new BLL.Setting();
                var settingItem = setting.Get();
                context.Response.Redirect(settingItem.SiteUrl);
            }

            public virtual bool IsReusable
            {
                get { return false; }
            }
        }

        public override void RemapHandler(HttpApplication context, IHandler handler, string fileName)
        {
            var setting = new BLL.Setting();
            var settingItem = setting.Get();
            var theme = HostingEnvironment.MapPath("~/Theme/" + settingItem.WapTheme.IifNullOrWhiteSpace("Wap") + "/");
            var path = theme + fileName;
            if (!File.Exists(path)) path = Path.ChangeExtension(path, "vbhtml");
            handler.FileName = path;
            if (Parser.CONFIGWAP != null) handler.ContentType = Parser.CONFIGWAP.ContentType.IifNullOrWhiteSpace("text/vnd.wap.wml");
            context.Context.RemapHandler(handler);
        }

        public override void Category(HttpApplication context, Model.Category item)
        {
            this.RemapHandler(context, new Handler<Template.Category.TemplateList, Model.Category>(item), "List.cshtml");
        }

        public override void Post(HttpApplication context, Model.Post item)
        {
            this.RemapHandler(context, new Handler<Template.Post.Template, Model.Post>(item), "Post.cshtml");
        }

        public override void Job(HttpApplication context, Model.Job item)
        {
            this.RemapHandler(context, new Handler<Template.Job.Template, Model.Job>(item), "Job.cshtml");
        }

        public override bool Rewrite(HttpApplication context, string url)
        {
            return false;
        }

        public override UrlElementCollection Urls
        {
            get { return Parser.CONFIGWAP != null ? Parser.CONFIGWAP.Urls : null; }
        }

        public override void Init(HttpApplication context)
        {
            var request = context.Request;
            var userAgent = request.UserAgent;
            if (userAgent != null && Parser.CONFIGWAP != null && !Parser.CONFIGWAP.Debug && userAgent.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) != -1)
                context.Context.RemapHandler(new Home());
            else
                base.Init(context);
        }
    }
}
