using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web.Http;
using agi = HtmlAgilityPack;


namespace Project
{
    public struct MethodResult : IEquatable<MethodResult>
    {
        public string Content;
        public byte[] Contentb;
        public string Redirecturl;

        public override bool Equals(object obj)
        {
            if (!(obj is MethodResult))
                return false;

            return Equals((MethodResult)obj);
        }

        public override int GetHashCode()
        {
            if (Contentb == null)
                return Content.GetHashCode() ^ Redirecturl.GetHashCode();
            else
                return Content.GetHashCode() ^ Redirecturl.GetHashCode() ^ Contentb.GetHexString().GetHashCode();

        }

        public bool Equals(MethodResult other)
        {
            if (Content != other.Content)
                return false;

            if (Redirecturl != other.Redirecturl)
                return false;

            return Contentb == other.Contentb;
        }


        public static bool operator ==(MethodResult point1, MethodResult point2)
        {
            return point1.Equals(point2);
        }

        public static bool operator !=(MethodResult point1, MethodResult point2)
        {
            return !point1.Equals(point2);
        }
    }

    sealed class PostRequest : Attribute
    {

    }

    public class BaseController : ApiController
    {
        public string QueryString { get; set; }
        public string PostData { get; set; }
        public string ParamData { get; set; }

        protected string Trig_Ctrl { get; set; }
        protected string Trig_func { get; set; }

        public PageModel GetGlobalModel()
        {
            var config = RequestContext.Configuration;
            var routeData = config.Routes.GetRouteData(Request).Values.ToList();
            var name_ctrl = routeData[0].Value.ToString();
            var name_action = routeData[1].Value.ToString();


            return new PageModel
            {
                RouteData = routeData,
                urlcontrol = name_ctrl,
                urlaction = name_action
            };
        }


        public MethodResult View()
        {
            var config = RequestContext.Configuration;
            if (config != null)
            {
                var routeData = config.Routes.GetRouteData(Request).Values.ToList();
                var name_ctrl = routeData[0].Value.ToString();
                var name_action = routeData[1].Value.ToString();
                return View(name_ctrl, name_action);
            }
            else
            {
                return View(Trig_Ctrl + "/" + Trig_func);
            }

        }

        public static void ApplyCommonValue(ref string contents)
        {
            //메뉴 푸터 - 개발자 정보

        }

        public MethodResult View(string Controller, string Action, Boolean applydefaultview = true)
        {
            var retval = new MethodResult();

            if (Action.IndexOf(".") == -1)
                Action += ".html"; //기본값 html 을 넣는다

            var file = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "View", Controller, Action);

            var contents = string.Empty;

            if (System.IO.File.Exists(file) == false)
            {
                //error 폴더의 404.html 파일을 찾는다.
                var file404 = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "View", "Error", "404.html");
                if (System.IO.File.Exists(file404))
                {
                    contents = System.IO.File.ReadAllText(file404, System.Text.Encoding.UTF8);
                    contents = contents.Replace("{errorfilename}", file);
                }

                else
                    contents = "ERROR CODE - 404 (NOT FOUND) <br />" + file;

                Console.WriteLine("view File not found : " + file);
            }
            else
            {
                //디폴트뷰의 내용을 가져온다 (있다면 적용한다)
                if (applydefaultview)
                {
                    //뷰파일이 있다면 그것을 적용한다
                    var laytoutfile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "View", "Layout", "default.html");
                    if (System.IO.File.Exists(laytoutfile))
                        contents = System.IO.File.ReadAllText(laytoutfile, System.Text.Encoding.UTF8);

                    var fileContents = System.IO.File.ReadAllText(file, System.Text.Encoding.UTF8);
                    if (String.IsNullOrEmpty(contents)) contents = fileContents;
                    else contents = contents.Replace("{contents}", fileContents);
                }
                else
                {
                    //해당 뷰를 가져와서 반환한다
                    contents = System.IO.File.ReadAllText(file, System.Text.Encoding.UTF8);
                }
            }

            agi.HtmlDocument doc = new agi.HtmlDocument();
            doc.LoadHtml(contents);

            //파일참조 태그를 모두 가져옴
            var tags_include = doc.QuerySelectorAll("include");
            foreach (var item in tags_include)
            {
                var filename = item.InnerText;

                var load_file = String.Concat(AppDomain.CurrentDomain.BaseDirectory, "View", filename.Replace("/", "\\"));
                load_file = load_file.Replace("\\\\", "\\");
                String fileContents;// = String.Empty;

                Console.WriteLine("## " + item.OuterHtml);
                if (System.IO.File.Exists(load_file))
                {
                    fileContents = System.IO.File.ReadAllText(load_file, System.Text.Encoding.UTF8);
                }
                else
                {
                    fileContents = string.Format("<div class=\"fg-red\">#include Error:nofile:{0}</div>",
                        filename);    //파일이없다면 해당 부분은 오류 처리한다.
                }
                contents = contents.Replace(item.OuterHtml, fileContents);
            }

            //콘텐츠내의 file 을 찾아서 처리한다. ; 정규식의 처리속도가 느릴듯하여,  그냥 처리해본다


            //시스템변수 replace
            contents = contents.Replace("{param_control}", Trig_Ctrl);
            contents = contents.Replace("{param_function}", Trig_func);

            retval.Content = contents;
            return retval;
        }
        public MethodResult View(string viewfilename, Boolean applydefaultview = true)
        {
            var retval = new MethodResult();

            if (viewfilename.IndexOf(".") == -1)
                viewfilename += ".html"; //기본값 html 을 넣는다

            var file = AppDomain.CurrentDomain.BaseDirectory + "View" + viewfilename.Replace("/", "\\");

            var contents = string.Empty;

            if (System.IO.File.Exists(file) == false)
            {
                //error 폴더의 404.html 파일을 찾는다.
                var file404 = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "View", "Error", "404.html");
                if (System.IO.File.Exists(file404))
                {
                    contents = System.IO.File.ReadAllText(file404, System.Text.Encoding.UTF8);
                    contents = contents.Replace("{errorfilename}", file);
                }

                else
                    contents = "ERROR CODE - 404 (NOT FOUND) <br />" + file;

                Console.WriteLine("view File not found : " + file);
            }
            else
            {
                //디폴트뷰의 내용을 가져온다 (있다면 적용한다)
                if (applydefaultview)
                {
                    //뷰파일이 있다면 그것을 적용한다
                    var laytoutfile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "View", "Layout", "default.html");
                    if (System.IO.File.Exists(laytoutfile))
                        contents = System.IO.File.ReadAllText(laytoutfile, System.Text.Encoding.UTF8);

                    var fileContents = System.IO.File.ReadAllText(file, System.Text.Encoding.UTF8);
                    if (String.IsNullOrEmpty(contents)) contents = fileContents;
                    else contents = contents.Replace("{contents}", fileContents);
                }
                else
                {
                    //해당 뷰를 가져와서 반환한다
                    contents = System.IO.File.ReadAllText(file, System.Text.Encoding.UTF8);
                }
            }

            //콘텐츠내의 file 을 찾아서 처리한다. ; 정규식의 처리속도가 느릴듯하여,  그냥 처리해본다
            while (true)
            {
                var fileindexS = contents.IndexOf("{file:");
                if (fileindexS == -1) break;
                var fileindexE = contents.IndexOf("}", fileindexS);
                if (fileindexE == -1) break;
                if (fileindexE <= fileindexS + 5) break;
                var inlinestr = contents.Substring(fileindexS, fileindexE - fileindexS + 1);
                var filename = contents.Substring(fileindexS + 7, fileindexE - fileindexS - 8);
                var load_file = String.Concat(AppDomain.CurrentDomain.BaseDirectory, "View", "\\", filename.Replace("/", "\\"));
                load_file = load_file.Replace("\\\\", "\\");
                String fileContents;// = String.Empty;

                Console.WriteLine("file impot : " + load_file);
                if (System.IO.File.Exists(load_file))
                {
                    fileContents = System.IO.File.ReadAllText(load_file, System.Text.Encoding.UTF8);
                }
                else
                {
                    fileContents = "{FileNotFound:" + filename + "}";    //파일이없다면 해당 부분은 오류 처리한다.
                }
                contents = contents.Replace(inlinestr, fileContents);
            }

            //시스템변수 replace
            contents = contents.Replace("{param_control}", Trig_Ctrl);
            contents = contents.Replace("{param_function}", Trig_func);

            retval.Content = contents;
            return retval;
        }
        protected class Parameter
        {
            public string Key { get; set; }
            public string Value { get; set; }
            public Parameter(string key_, string value_)
            {
                Key = key_;
                Value = value_;
            }
        }

    }
}
