using System;
using System.IO;
using System.Data;
using System.Configuration;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Globalization;
using TABS.MailCarrier.AuxLib;
using TABS.MailCarrier.WebSDK.Mail;

/// <summary>
/// 웹 출력, 바이러스 검사 등과 같은 유틸리티 메서드를 제공한다.
/// </summary>
public class WebUtil
{
    public WebUtil()
    {
    }

    /// <summary>
    /// 파일 크기를 용량에 따라 다른 포맷의 문자열로 반환한다.
    /// </summary>
    /// <param name="fileSize">파일 크기</param>
    /// <returns></returns>
    public static string GetFormattedFileSize(long fileSize)
    {
        if (fileSize == 0)
            return "0KB";
        else if (fileSize < 1024)
            return "1KB";
        else if (fileSize < 1024 * 1024)
            return string.Format("{0:N0}KB", fileSize / 1024);
        else if (fileSize < 1024 * 1024 * 1024)
            return string.Format("{0:N1}MB", fileSize / (1024 * 1024.0));
        else
            return string.Format("{0:N1}GB", fileSize / (1024 * 1024 * 1024.0));
    }

    /// <summary>
    /// 일반 텍스트를 HTML로 출력하기 위해 변환해서 반환한다.
    /// </summary>
    /// <param name="text">일반 텍스트</param>
    /// <returns></returns>
    public static string GetFormattedPlainText(string text)
    {
        return GetFormattedPlainText(text, false);
    }

    /// <summary>
    /// 일반 텍스트를 HTML로 출력하기 위해 변환해서 반환한다.
    /// </summary>
    /// <param name="text">일반 텍스트</param>
    /// <param name="processCrlf">true면 CRLF를 div 태그로 변경한다.</param>
    /// <returns></returns>
    public static string GetFormattedPlainText(string text, bool processCrlf)
    {
        string html = HttpUtility.HtmlEncode(text);
        if (processCrlf)
        {
            // 줄 단위로 분리
            string[] lines = html.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);

            // 각 줄을 <div>로 감싸기
            html = "";
            foreach (string line in lines)
            {
                html += string.Format("<div>{0}</div>\n", line.Length > 0 ? line : "&nbsp;");
            }
        }
        return html;
    }

    /// <summary>
    /// 주어진 html을 &lt;div id="mc_container"&gt;로 감싸서 반환한다.
    /// </summary>
    /// <param name="html"></param>
    /// <returns></returns>
    public static string GetHtmlWithContainer(string html)
    {
        TABS.MailCarrier.AuxLib.HtmlStripper htmlStripper = new TABS.MailCarrier.AuxLib.HtmlStripper();
        html = htmlStripper.GetEditableHtml(html);

        return (html.IndexOf("<div id=\"mc_container\"") == 0) ? html :
            string.Format("<div id=\"mc_container\" style=\"font-family:{0};font-size:{1};line-height:{2};\">{3}</div>",
                AppSetting.EditorDefaultFont, AppSetting.EditorDefaultFontSize, AppSetting.EditorDefaultLineHeight, html);
    }

    /// <summary>
    /// html/head/body 테그를 포함한 완전한 HTML을 구성해서 반환한다.
    /// </summary>
    /// <param name="html"></param>
    /// <returns></returns>
    public static string GetFullHtmlWithContainer(string html)
    {
        TABS.MailCarrier.AuxLib.HtmlStripper htmlStripper = new TABS.MailCarrier.AuxLib.HtmlStripper();
        html = htmlStripper.GetEditableHtml(html);

        string chtml = (html.IndexOf("<div id=\"mc_container\"") == 0) ? html :
            string.Format("<div id=\"mc_container\" style=\"font-family:{0};font-size:{1};line-height:{2};\">{3}</div>",
                AppSetting.EditorDefaultFont, AppSetting.EditorDefaultFontSize, AppSetting.EditorDefaultLineHeight, html);
        return string.Format("<html><head><style>p{{margin-top:0px;margin-bottom:0px;}}</style></head><body>{0}</body></html>", chtml);
    }

    /// <summary>
    /// c# 문자열을 자바스크립트 string에 사용할 수 있도록 인코딩해서 반환한다.
    ///  - ""로 둘러싸인 문자열로 사용되는 경우
    /// </summary>
    /// <param name="s">c# 문자열</param>
    /// <returns>자바스크립트 string</returns>
    [Obsolete("EncodeJsString2 사용을 권고합니다.")]
    public static string EncodeJsString(string s)
    {
        StringBuilder sb = new StringBuilder();
        foreach (char c in s)
        {
            switch (c)
            {
                case '\"':
                    sb.Append("\\\"");
                    break;
                case '\\':
                    sb.Append("\\\\");
                    break;
                case '\b':
                    sb.Append("\\b");
                    break;
                case '\f':
                    sb.Append("\\f");
                    break;
                case '\n':
                    sb.Append("\\n");
                    break;
                case '\r':
                    sb.Append("\\r");
                    break;
                case '\t':
                    sb.Append("\\t");
                    break;
                default:
                    int i = (int)c;
                    if (i < 32 || i > 127)
                    {
                        sb.AppendFormat("\\u{0:X04}", i);
                    }
                    else
                    {
                        sb.Append(c);
                    }
                    break;
            }
        }
        return sb.ToString();
    }

    /// <summary>
    /// c# 문자열을 자바스크립트 string에 사용할 수 있도록 인코딩해서 반환한다.
    ///  - ''로 둘러싸인 문자열로 사용되는 경우
    /// </summary>
    /// <param name="s">c# 문자열</param>
    /// <returns>자바스크립트 string</returns>
    public static string EncodeJsString2(string s)
    {
        // JavaScriptStringEncode 기본 동작 
        //   single quotation marks -> \u0027
        //   double quotation marks -> \" 
        // 아래와 같이 태그 내 스크립트를 사용할 경우 "가 문제가 되므로 \" 를 &#34로 변환
        // <a href="javascript:func('A\"BC\"D')" />
        return HttpUtility.JavaScriptStringEncode(s).Replace("\\\"", "&#34");
        /*
        StringBuilder sb = new StringBuilder();
        foreach (char c in s)
        {
            switch (c)
            {
                case '\'':
                    sb.Append("\\\'");
                    break;
                case '\\':
                    sb.Append("\\\\");
                    break;
                case '\b':
                    sb.Append("\\b");
                    break;
                case '\f':
                    sb.Append("\\f");
                    break;
                case '\n':
                    sb.Append("\\n");
                    break;
                case '\r':
                    sb.Append("\\r");
                    break;
                case '\t':
                    sb.Append("\\t");
                    break;
                case '\"':
                    sb.Append("&#34");
                    break;
                default:
                    int i = (int)c;
                    if (i < 32 || i > 127)
                    {
                        sb.AppendFormat("\\u{0:X04}", i);
                    }
                    else
                    {
                        sb.Append(c);
                    }
                    break;
            }
        }
        return sb.ToString();
        */
    }

    /// <summary>
    /// 파일에 대해 바이러스 검사를 실행한다.
    /// </summary>
    /// <param name="filePath">검사할 파일 경로(완전한 경로 필요)</param>
    /// <param name="result">검사 결과 문자열</param>
    /// <returns>바이러스 검출시 true를 반환</returns>
    public static bool VirusInfected(string filePath, out string result)
    {
        if (!AppSetting.EnableVirusCheck)
        {
            result = Resources.Mail.NoVirusCheck;
            return false;
        }
        bool infected = false;
        try
        {
            AntiVirus av = new AntiVirus();
            if (av.Open())
            {
                bool found, licenseExpire;
                string virusName = "";
                av.CheckVirus(filePath, out found, out virusName, out licenseExpire);
                result = found ? virusName : (licenseExpire ? Resources.Mail.NoVirusCheck : Resources.Mail.NoVirus);
                av.Close();
                infected = found;
            }
            else
            {
                result = Resources.Mail.NoVirusCheck;
            }
        }
        catch
        {
            result = Resources.Mail.NoVirusCheck;
        }
        return infected;
    }

    /// <summary>
    /// 왼쪽 메뉴에 텍스트 출력시 가로 폭을 넘지 않도록 트리밍한다.
    /// </summary>
    /// <param name="indent">들여쓰기 간격</param>
    /// <param name="name">출력 텍스트</param>
    /// <returns>트리밍된 텍스트 반환</returns>
    public static string GetTrimmedName(int indent, string name)
    {
        int maxLength = 20;

        int idx = (indent * 2);
        string folderName = "";
        foreach (char ch in name.ToCharArray())
        {
            if (idx > maxLength)
            {
                folderName += "...";
                break;
            }
            if (char.GetUnicodeCategory(ch) ==
                UnicodeCategory.OtherLetter)
            {
                idx += 2;
            }
            else
            {
                idx += 1;
            }
            folderName += ch.ToString();
        }

        return folderName;
    }

    public static string GetStrippedHtml(string html, bool addLineBreak = false)
    {
        HtmlStripper htmlStripper = new HtmlStripper();
        return htmlStripper.Strip(html, addLineBreak);
    }

    public static string GetHtml4WebEditor(string html)
    {
        HtmlStripper htmlStripper = new HtmlStripper();
        return htmlStripper.GetEditableHtml(html);
    }

    public static string InvalidAttachFileName(string attach)
    {
        char[] invalidChars = Path.GetInvalidFileNameChars();
        foreach (char ch in invalidChars)
        {
            attach = attach.Replace(ch, '_');
        }

        string fileName = Path.GetFileNameWithoutExtension(attach);
        string fileExtension = Path.GetExtension(attach);
        int maxLength = (fileName.Length >= 100) ? 100 : fileName.Length;
        return string.Format("{0}{1}", fileName.Substring(0, maxLength), fileExtension);
    }

    /// <summary>
    /// Kendo UI를 사용하는 페이지에서 언어별 리소스를 로딩한다.
    ///  - Page_Init()에서 호출
    /// </summary>
    /// <param name="header"></param>
    /// <param name="language"></param>
    public static void SetKendoUiLocalResource(HtmlHead header, string language)
    {
        if (language == "ko")
        {
            LiteralControl kendoLangJs = new LiteralControl(
                "<script src=\"../libs/kendoui/2023.3.1114/mjs/cultures/kendo.culture.ko-KR.js\" type=\"module\"></script>" +
                "<script src=\"../libs/kendoui/2023.3.1114/mjs/messages/kendo.messages.ko-KR.js\" type=\"module\"></script>"
               );
            header.Controls.Add(kendoLangJs);
        }
    }
    public static void SetKendoUiLocalResource2(HtmlHead header, string language)
    {
        if (language == "ko")
        {
            LiteralControl kendoLangJs = new LiteralControl(
                "<script src=\"../../libs/kendoui/2023.3.1114/mjs/cultures/kendo.culture.ko-KR.js\" type=\"module\"></script>" +
                "<script src=\"../../libs/kendoui/2023.3.1114/mjs/messages/kendo.messages.ko-KR.js\" type=\"module\"></script>"
               );
            header.Controls.Add(kendoLangJs);
        }
    }

    /// <summary>
    /// mc.common1.css 파일을 로딩한다.
    ///  - Page_Init()에서 호출
    /// </summary>
    /// <param name="header"></param>
    public static void SetMcCommonCss(HtmlHead header)
    {
        LiteralControl css = new LiteralControl("<link rel=\"stylesheet\" type=\"text/css\" href=\"../css/mc.common1.css" + AppSetting.CssVer + "\" />");
        header.Controls.Add(css);
        if (AppSetting.SupportDarkMode)
        {
            LiteralControl css4dark = new LiteralControl("<link rel=\"stylesheet\" type=\"text/css\" href=\"../css/mc.common1.dark.css" + AppSetting.CssVer + "\" />");
            header.Controls.Add(css4dark);
        }
    }

    public static void SetMcCommonCss2(HtmlHead header)
    {
        LiteralControl css = new LiteralControl("<link rel=\"stylesheet\" type=\"text/css\" href=\"../../css/mc.common1.css" + AppSetting.CssVer + "\" />");
        header.Controls.Add(css);
        if (AppSetting.SupportDarkMode)
        {
            LiteralControl css4dark = new LiteralControl("<link rel=\"stylesheet\" type=\"text/css\" href=\"../../css/mc.common1.dark.css" + AppSetting.CssVer + "\" />");
            header.Controls.Add(css4dark);
        }
    }

    public static void SetMcCommonCss3(HtmlHead header)
    {
        LiteralControl css = new LiteralControl("<link rel=\"stylesheet\" type=\"text/css\" href=\"css/mc.common1.css" + AppSetting.CssVer + "\" />");
        header.Controls.Add(css);
        if (AppSetting.SupportDarkMode)
        {
            LiteralControl css4dark = new LiteralControl("<link rel=\"stylesheet\" type=\"text/css\" href=\"css/mc.common1.dark.css" + AppSetting.CssVer + "\" />");
            header.Controls.Add(css4dark);
        }
    }
}
