﻿using System;
using System.Globalization;
using System.Web;
using System.Web.UI;
using System.IO;
using System.Net;
using System.Configuration;
using System.Xml;
using System.Xml.Xsl;
using System.Web.Mvc;
using System.Text;

namespace Ssemi.Common.Core
{
    public enum HttpMethod { GET, POST, PUT, DELETE };

	/// <summary>Web utility library</summary>
	public static class WebLibrary
	{
		#region GetRefferPath(): 참조 경로를 구한다.
		/// <summary>참조 경로(HTTP_REFERER)에서 호스트를 제외한 경로를 구한다.</summary>
		/// <param name="usefullpath">호스트를 제외한 전체 경로를 반환 할 것인지 여부.(ex: <c>true</c>-/Path/FileName.aspx, <c>false</c>-FileName.aspx)</param>
		/// <returns>참조 경로(HTTP_REFERER, (ex:/Path/FileName.aspx or FileName.aspx))</returns>
		public static string GetRefferPath(bool usefullpath) {
			string HTTP_HOST = HttpContext.Current.Request.ServerVariables["HTTP_HOST"].FixNull();
			string HTTP_REFERER = HttpContext.Current.Request.ServerVariables["HTTP_REFERER"].FixNull();
			string refer = HTTP_REFERER.Replace("http://", string.Empty).Replace("https://", string.Empty).Replace(HTTP_HOST, string.Empty);
			int idx = refer.LastIndexOf('?');

			if (idx > 0) {
				refer = refer.Remove(idx);
			}

			if (!usefullpath) {
				refer = refer.Substring(refer.LastIndexOf('/') + 1);
			}

			return refer;
		}
		/// <summary>참조 경로(HTTP_REFERER)에서 호스트를 제외한 경로를 구한다.</summary>
		/// <returns>참조 경로(HTTP_REFERER, (ex:/Path/FileName.aspx))</returns>
		public static string GetRefferPath() {
			return GetRefferPath(true);
		}
		#endregion

		#region CompareReferPath()
		/// <summary>참조 경로값 비교</summary>
		/// <param name="target">대상 경로</param>
		/// <param name="usefullpath">호스트를 제외한 전체 경로를 사용 할 것인지 여부. (ex: <c>true</c>-/Path/FileName.aspx, <c>false</c>-FileName.aspx)</param>
		/// <returns>비교 결과 : True-대상 경로와 참조 경로가 같음, False-대상 경로와 참조 경로가 다름</returns>
		public static bool CompareReferPath(this object[] target, bool usefullpath) {
			bool rtnval = false;
			if (target.Length > 0) {
				for (int i = 0; i < target.Length; i++) {
					rtnval = CompareReferPath(target[i].FixNull(), usefullpath);
					if (rtnval) {
						break;
					}
				}
			}
			return rtnval;
		}
		/// <summary>참조 경로값 비교</summary>
		/// <param name="target">대상 경로</param>
		/// <returns>비교 결과 : True-대상 경로와 참조 경로가 같음, False-대상 경로와 참조 경로가 다름</returns>
		public static bool CompareReferPath(this object [] target) {
			return CompareReferPath(target, true);
		}
		/// <summary>참조 경로값 비교</summary>
		/// <param name="target">대상 경로</param>
		/// <param name="usefullpath">호스트를 제외한 전체 경로를 사용 할 것인지 여부. (ex: <c>true</c>-/Path/FileName.aspx, <c>false</c>-FileName.aspx)</param>
		/// <returns>비교 결과 : True-대상 경로와 참조 경로가 같음, False-대상 경로와 참조 경로가 다름</returns>
		public static bool CompareReferPath(this object target, bool usefullpath) {
			return GetRefferPath(usefullpath).CompareValue(target, true);
		}
		/// <summary>참조 경로값 비교</summary>
		/// <param name="target">대상 경로</param>
		/// <returns>비교 결과 : True-대상 경로와 참조 경로가 같음, False-대상 경로와 참조 경로가 다름</returns>
		public static bool CompareReferPath(string target) {
			return GetRefferPath(true).CompareValue(target, true);
		}
		/// <summary>참조 경로값 비교</summary>
		/// <param name="target">대상 경로</param>
		/// <returns>비교 결과 : True-대상 경로와 참조 경로가 같음, False-대상 경로와 참조 경로가 다름</returns>
		public static bool CompareExternalReferPath(this object [] target) {
			bool rtnval = false;
			if (target.Length > 0) {
				for (int i = 0; i < target.Length; i++) {
					rtnval = CompareExternalReferPath(target[i].FixNull());
					if (rtnval) {
						break;
					}
				}
			}
			return rtnval;
		}
		/// <summary>참조 경로값 비교</summary>
		/// <param name="target">대상 경로( ex: http://entoro.com/Path/FileName.aspx )</param>
		/// <returns>비교 결과 : True-대상 경로와 참조 경로가 같음, False-대상 경로와 참조 경로가 다름</returns>
		public static bool CompareExternalReferPath(this object target) {
			return HttpContext.Current.Request.ServerVariables["HTTP_REFERER"].CompareValue(target, true);
		}
		#endregion

		#region NL2BR()
		/// <summary>
		/// <![CDATA[
		/// NL2BR은 PHP에서 따온 이름이다.
		/// 리턴 코드를 로 <BR />바꾸는 작용( New Line to <BR />) 을 한다..
		/// ]]>
		/// </summary>
		/// <param name="target">대상 객체</param>
		/// <returns>변환된 문자열</returns>
		public static string NL2BR(this object target) {
			return target.FixNull().Replace("\r\n", "<br />[#R#][#N#]").Replace("\r", "<br />[#R#]").Replace("\n", "<br />[#N#]").Replace("[#R#]", "\r").Replace("[#N#]", "\n");
		}
        public static string BR2NL(this object target) {
            return target.FixNull().Replace("<br />", "\r\n").Replace("<br>", "\r\n").Replace("<br/>", "\r\n");
        }
        #endregion

		#region ToHtmlString()
		/// <summary>
		/// <![CDATA[
		/// 문자열을 HTML로 변경한다.
		/// ]]>
		/// </summary>
		/// <param name="target">대상 객체</param>
		/// <returns>변환된 문자열</returns>
		public static string ToHtmlString(this object target) {
			return target.DEHtmlSpecialChars().Replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;").Replace(" ", "&nbsp;").LinkUrl("_blank").LinkEmail().NL2BR();
		}
		#endregion

		#region SetCookie() & GetCookie()
		/// <summary>쿠키 생성</summary>
		/// <param name="name">쿠키 이름</param>
		/// <param name="value">쿠키값</param>
		public static void SetCookie(object value, string name) {
			SetCookie(value, name, null, null);
		}
		/// <summary>쿠키 생성</summary>
		/// <param name="name">쿠키 이름</param>
		/// <param name="value">쿠키값</param>
		/// <param name="domain">쿠키 도메인</param>
		/// <param name="path">쿠키 경로</param>
		public static void SetCookie(object value, string name, string domain, string path) {
			HttpCookie coo = new HttpCookie(name.FixNull(), value.FixNull());
			if (domain.FixNull().Length > 0) {
				coo.Domain = domain;
			}
			if (path.FixNull().Length > 0) {
				coo.Path = path;
			}
			HttpContext.Current.Response.Cookies.Add(coo);
		}
		/// <summary>쿠키 생성</summary>
		/// <param name="name">쿠키 이름</param>
		/// <param name="value">쿠키값</param>
		/// <param name="domain">쿠키 도메인</param>
		/// <param name="path">쿠키 경로</param>
		/// <param name="expires">쿠키 만료일</param>
		public static void SetCookie(object value, string name, string domain, string path, DateTime expires) {
			HttpCookie coo = new HttpCookie(name.FixNull(), value.FixNull());
			if (domain.FixNull().Length > 0) {
				coo.Domain = domain;
			}
			if (path.FixNull().Length > 0) {
				coo.Path = path;
			}
			coo.Expires = expires;
			HttpContext.Current.Response.Cookies.Add(coo);
		}
		/// <summary>
		/// 쿠키값 읽어오기
		/// </summary>
		/// <param name="name">쿠키 이름</param>
		/// <returns>쿠키값</returns>
		public static string GetCookie(string name) {
			string rtn = string.Empty;
			if (HttpContext.Current.Request.Cookies[name] != null) {
				rtn = HttpContext.Current.Request.Cookies[name].Value.FixNull();
			}
			return rtn;
		}
		/// <summary>쿠키값 읽어오기</summary>
		/// <param name="idx">쿠키 인덱스</param>
		/// <returns>쿠키값</returns>
		public static string GetCookie(int idx) {
			string rtn = string.Empty;
			if (HttpContext.Current.Request.Cookies[idx] != null) {
				rtn = HttpContext.Current.Request.Cookies[idx].Value.FixNull();
			}
			return rtn;
		}
		#endregion

		#region GetLinkedText(): 문자열중에 HTTP URI형식의문자열을 Link(Anchor)로 변환
		/// <summary>
		/// HTTP URI를 링크로 바꿔줌
		/// </summary>
		/// <param name="str">문자열</param>
		/// <param name="target">대상 프래임</param>
		/// <returns></returns>
		public static string LinkUrl(this object str, string target) {
			return str.FixNull().RegExReplace("((news|(ht|f)tp(s?)\\://){1}\\S+)", string.Format(CultureInfo.CurrentCulture, "<a href='$0' target='{0}'>$0</a>", target));
		}
		/// <summary>
		/// HTTP URI를 링크로 바꿔줌
		/// </summary>
		/// <param name="str">문자열</param>
		/// <returns></returns>
		public static string LinkUrl(this object str) {
			return str.FixNull().RegExReplace("((news|(ht|f)tp(s?)\\://){1}\\S+)", "<a href='$0'>$0</a>");
		}
		/// <summary>
		/// E-Maill Address에 자동 링크를 걸기 위해 만든 태그
		/// </summary>
		/// <param name="str">문자열</param>
		/// <returns>링크된 문자열</returns>
		public static string LinkEmail(this object str) {
			return StringUtil.RegExReplace(str, "^[^_][a-zA-Z0-9_]+[^_]@{1}[a-z]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$", "<a href='mailto:$0'>$0</a>");
		}
		/// <summary>
		/// 문자열중에 HTTP URI형식의문자열을 Link(Anchor)로 변환
		/// </summary>
		/// <param name="str">The STR.</param>
		/// <returns></returns>
		public static string GetLinkedText(this object str) {
			return str.LinkEmail().LinkUrl();
		}
		#endregion

		#region ParentsDirName: Get the parents directory name
		/// <summary>부모 디렉토리명 구하기</summary>
		public static string ParentsDirName {
			get {
				return (HttpContext.Current.Request.Path.Replace(HttpContext.Current.Request["HTTP_HOST"].ToString(CultureInfo.CurrentCulture), string.Empty).Split('/')[1]);
			}
		}
		#endregion

		#region ResolveUrl() : URL를 사용자가 호출할 수 있는 경로로 변환
		/// <summary>URL를 사용자가 호출할 수 있는 경로로 변환</summary>
		/// <param name="RelativeUrl">변환할 URL</param>
		/// <returns>변환된 경로</returns>
		public static string ResolveUrl(this string RelativeUrl) {
			using (Control ctl = new Control()) {
				return ctl.ResolveUrl(RelativeUrl);
			}
		}
		#endregion

		#region UrlReqeust() : URL 불러오기
		/// <summary>
		/// Url 불러오기
		/// </summary>
		/// <param name="strUrl">주소</param>
		/// <returns></returns>
		public static string UrlRequest(string strUrl)
		{
            return UrlRequest(strUrl, HttpMethod.GET, "", "");
		}
        
		/// <summary>
		/// Url 불러오기
		/// </summary>
		/// <param name="strUrl">주소</param>
		/// <param name="strPost">paramters</param>
		/// <returns></returns>
        public static string UrlRequest(string strUrl, HttpMethod method = HttpMethod.GET, string strPost = "", string charset = "")
		{
			string result = string.Empty;

            HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(strUrl);
            objRequest.Method = method.ToString();

            #region HTTP POST
            if (method.Equals(HttpMethod.POST))
            {
                charset = !String.IsNullOrEmpty(charset) ? "charset=" + charset +";" : String.Empty;
                objRequest.ContentType = String.Format("application/x-www-form-urlencoded; {0}", charset);

                StreamWriter myWriter = null;
                try
                {
                    myWriter = new StreamWriter(objRequest.GetRequestStream(), Encoding.UTF8);
                    myWriter.Write(strPost);
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
                finally
                {
                    if (myWriter != null) myWriter.Close();
                }
            }
            #endregion

            using (StreamReader sr = new StreamReader(objRequest.GetResponse().GetResponseStream()))
            {
                result = sr.ReadToEnd();
                sr.Close();
            }
			return result;
		}
		#endregion

        public static Stream GetStreamUrlRequest(string strUrl, HttpMethod method = HttpMethod.GET, string strPost = "", string charset = "")
        {
            HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(strUrl);
            objRequest.Method = method.ToString();

            #region HTTP POST
            if (method.Equals(HttpMethod.POST))
            {
                charset = !String.IsNullOrEmpty(charset) ? "charset=" + charset + ";" : String.Empty;
                objRequest.ContentType = String.Format("application/x-www-form-urlencoded; {0}", charset);

                StreamWriter myWriter = null;
                try
                {
                    myWriter = new StreamWriter(objRequest.GetRequestStream(), Encoding.UTF8);
                    myWriter.Write(strPost);
                }
                catch
                {
                    
                }
                finally
                {
                    if (myWriter != null) myWriter.Close();
                }
            }
            #endregion

            return objRequest.GetResponse().GetResponseStream();
        }

        #region xml Transform 
        public static string XMLTransform(string xmlPath, string xslPath, ActionExecutedContext filterContext)
        {
            var action = filterContext.ActionDescriptor.ActionName.ToLower();
            var controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower();

            HttpRequest Request = HttpContext.Current.Request;
            
            string result = string.Empty;
            try
            {
                XmlDocument xdoc = new XmlDocument();
                xdoc.Load(xmlPath);

                XslCompiledTransform xsl = new XslCompiledTransform();
                xsl.Load(xslPath);

                XmlElement node = xdoc.DocumentElement;
                XmlElement n1 = xdoc.CreateElement("this_url");

                if (Request.QueryString.Count > 0)
                    n1.InnerText = string.Format("{0}?{1}", Request.ServerVariables["URL"], Request.QueryString);
                else
                    n1.InnerText = Request.ServerVariables["URL"];

                node.AppendChild(n1);

                n1 = xdoc.CreateElement("community");
                n1.InnerText = filterContext.Controller.ViewData["Community"].FixNull();
                node.AppendChild(n1);

                n1 = xdoc.CreateElement("controller");
                n1.InnerText = controller;
                node.AppendChild(n1);
                n1 = xdoc.CreateElement("action");
                n1.InnerText = action;
                node.AppendChild(n1);

                using (StringWriter sw = new StringWriter())
                {
                    //filterContext.Controller.ViewData["xml"] = "<xmp>" + xdoc.OuterXml + "</xmp>";
                    xsl.Transform(xdoc, null, sw);
                    result = sw.ToString();
                }
            }
            catch (Exception ex)
            {
                string errorMsg = ex.Message;
                throw;
            }
            return result;
        }
        #endregion

        
    }
}