using MahApps.Metro.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor
{
    /// <summary>
    /// InputBox.xaml 的交互逻辑
    /// </summary>
    public partial class InputBox : MetroWindow
    {
        /// <summary>
        /// [私有构造方法]用以创建一个输入窗口。
        /// 此类只用静态方法调用,所以不需要公有的构造方法。
        /// 调用方式:InputBox.Show(...);
        /// </summary>
        private InputBox()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 显示一个输入框,并获取输入的数据。
        /// </summary>
        /// <param name="title">输入框标题。</param>
        /// <param name="prompt">输入框中的提示文本。</param>
        /// <param name="defaultValue">输入框的默认文本。</param>
        /// <param name="isFilePath">是否应输入文件名。这会影响数据校验的结果。</param>
        /// <param name="prompt2">第二提示文本。</param>
        /// <param name="isPassword">是否打算输入密码。如果为真,输入时文本透明(不可见)。</param>
        public static string Show(string title, string prompt, string defaultValue, bool isFilePath, string prompt2 = null, bool isPassword = false)
        {
            InputBox ibx = new InputBox();
            ibx.Owner = App.Current.MainWindow;
            ibx.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            ibx.Icon = ibx.Owner.Icon;
            ibx.Title = title;
            ibx.tbxPrompt.Text = prompt;
            ibx.tbxInput.Text = defaultValue;
            ibx.IsPassword = isPassword;

            if (string.IsNullOrEmpty(prompt2))
            {
                ibx.tbxPrompt2.Visibility = Visibility.Collapsed;
            }
            else
            {
                ibx.tbxPrompt2.Visibility = Visibility.Visible;
                ibx.tbxPrompt2.Text = prompt2;
            }

            ibx.tbxInput.SelectAll();

            //已经可以支持直接取拼音首字母替换中文字符,不需要这个了。
            //if (isFilePath)
            //{
            //    Globals.SwitchInputMethod(Globals.MainWindow.ShowTitleInWorkspaceManager);
            //}

            if (isPassword)
            {
                //ibx.tbxInput.SelectionBrush =
                //ibx.tbxInput.CaretBrush =
                ibx.tbxInput.Foreground = Brushes.Transparent;
                Globals.SwitchInputMethod(Globals.MainWindow.ShowTitleInWorkspaceManager);
            }

            if (ibx.ShowDialog() == true)
            {
                if (isFilePath && isPassword == false)
                {
                    var result = ibx.tbxInput.Text.Replace(" ", "-");
                    if (result.StartsWith("_"))
                        result = result.Substring(1);

                    result = result.Replace("_", "-");
                    return result;
                }
                else
                {
                    return ibx.tbxInput.Text;//原文输出
                }
            }

            return null;
        }

        /// <summary>
        ///  密码应原文输出。
        /// </summary>
        public bool IsPassword { get; set; } = false;

        /// <summary>
        /// 完成输入。
        /// </summary>
        private void btnOK_Click(object sender, RoutedEventArgs e)
        {
            if (IsFilePath)
            {
                if (ValidateFilePath(this.tbxInput.Text, true) == false)
                {
                    if (ValidateFilePath(this.tbxInput.Text, false))
                    {
                        var result = LMessageBox.Show("  建议使用英文字母、数字来命名,并且最好以英文字母开头(某些网络设备对数字开头的文件名支持欠佳)。\r\n" +
                            "  文件名(或文件夹名)使用特殊字符或汉字可能导致编译出的 CHM 文档中某些链接无效。" +
                            "只有一定范围的汉字会被转换为拼音首字母,而其它字符不会转换,所以仍然可能出错。\r\n\r\n" +
                            "  你确定要这样做吗?",
                            Globals.AppName, MessageBoxButton.YesNo, MessageBoxImage.Warning, "NPA_UseSpecialCharForFileName");
                        // NPA_ means No Prompt Again.

                        if (result != MessageBoxResult.Yes) return;
                        else
                        {
                            this.DialogResult = true;
                            this.Close();
                            return;
                        }
                    }
                    else
                    {
                        //var forbidonChars1 = "\\ / : * \" < > |";
                        //var forbidonChars2 = @"+ "" # % & ( ) + , : ; < = > ? @ |";
                        //tbxPrompt2.Text = $"  文件名只能使用字母、数字、下划线(_)字符。\r\n  下列字符为 Windows 文件系统禁用字符:\r\n  {forbidonChars1}\r\n  下列特殊字符会造成编译后的 CHM 文件中出现路径错误:\r\n  {forbidonChars2}";// "文件名中不能包含:\\/:*\"<>|";
                        tbxPrompt2.Text = "  文件名只能使用字母、数字、下划线(_)字符,且应以字母开头(不能以下划线字符[_]和数字字符开头。\r\n" +
                            "  ※因为某些网络设备(或软件)对一些特殊字符支持很差。";
                        tbxPrompt2.Visibility = Visibility.Visible;
                        return;
                    }
                }
            }

            this.DialogResult = true;
            this.Close();
        }

        private bool isFilePath = true;
        /// <summary>
        /// 指明输入的文本是否应通过文件名规则校验。
        /// </summary>
        public bool IsFilePath
        {
            get { return isFilePath; }
            set { isFilePath = value; }
        }

        /// <summary>
        /// 与“MainWindow.cs”下的同名方法不同:禁止出现冒号和路径分割符。
        /// 只允许字母、数字、下划线、句点,且不能以下划线开头。
        /// </summary>
        /// <param name="text">文件短名。</param>
        /// <returns></returns>
        public static bool ValidateFilePath(string text, bool highLevel)
        {
            if (string.IsNullOrEmpty(text)) return false;
            if (text.StartsWith("_")) return false;

            if (highLevel)
            {

                foreach (char c in text)
                {
                    if (c >= 'a' && c <= 'z') continue;
                    if (c >= 'A' && c <= 'Z') continue;
                    if (c >= '0' && c <= '9') continue;
                    if (c == '_' || c == '.' || c == ' ') continue;

                    return false;
                }

                return true;
            }

            if (text.Contains("/") ||
               text.Contains("\\") ||
               text.Contains(":") ||
               text.Contains(":") || //已知全角冒号也会导致链接失效
               text.Contains("*") ||
               text.Contains("\"") ||
               text.Contains("<") ||
               text.Contains(">") ||
               text.Contains("|") ||
               text.Contains("[") || //方括号会导致图像链接文本切分时识别出错。
               text.Contains("]"))   //方括号会导致图像链接文本切分时识别出错。
            {
                return false;
            }

            foreach (char c in text)
            {
                //全角标点均可用,半角标点不允许前列特殊字符。另,
                //半角波形符用于资源文件夹,不可用。
                //下划线用于目录元文件,不可用。
                //反引号符备用,不可用。
                //右面这些字符是 URL 要转义的,所以不能使用:+"#%&()+,/:;<=>?@\|
                if (@"+""#%&()+,/:;<=>?@\|".Contains(c)) return false;
                if ("!@$^-{}',.~·@#¥%…&*()【】{}|;‘’“”,。《〈〉》?".Contains(c)) continue;
                //已知全角冒号也会导致 Markdown 文件转换成 Html 文件后图像链接失效。
                //全角字符就算是特殊符号也是可以的
                //全角小写字母
                if (c == '、') continue;
                if (c >= 'a' && c <= 'z') continue;
                //全角大写字母
                if (c >= 'A' && c <= 'Z') continue;
                //!"#$%&'()*+,-./
                if (c >= '!' && c <= '/') continue;
                //全角数字
                if (c >= '0' && c <= '9') continue;
                //:;<=>?@
                if (c >= ':' && c <= '@') continue;
                //[\]^_`
                if (c >= '[' && c <= '`') continue;
                //{|}~
                if (c >= '{' && c <= '~') continue;
                //¢£¬ ̄¦¥
                if (c >= '¢' && c <= '¥') continue;
                //全角字符就算是特殊符号也是可以的

                //全角问号'?',就是>0x9fbb的。
                if (c > 0x9fbb)
                {
                    if (c == '§') continue;
                    if (c == '☆') continue;
                    if (c == '★') continue;
                    if (c == '○') continue;
                    if (c == '●') continue;
                    if (c == '◎') continue;
                    if (c == '◇') continue;
                    if (c == '◆') continue;
                    if (c == '□') continue;
                    if (c == '■') continue;
                    if (c == '△') continue;
                    if (c == '▲') continue;
                    if (c == '※') continue;
                    if (c == '〓') continue;
                    if (c == '#') continue;
                    if (c == '&') continue;
                    if (c == '@') continue;
                    if (c == '_') continue;
                    if (c == ' ̄') continue;

                    return false;
                }

                if (c < 0x4e00)
                {
                    if (c >= '0' && c <= '9') continue;
                    if (c == '_') continue;
                    if (c == '+') continue;
                    if (c == '-') continue;
                    if (c == '.') continue;//后缀名需要
                    if (c == '=') continue;
                    if (c == ' ') continue;
                    if (c == '(') continue;
                    if (c == ')') continue;
                    if (c == ')') continue;
                    if (c == '(') continue;
                    if (c >= '⑴' && c <= '⒇') continue;
                    if (c >= '①' && c <= '⑩') continue;
                    if (c >= '⒈' && c <= '⒛') continue;
                    if (c >= 'A' && c <= 'Z') continue;
                    if (c >= 'a' && c <= 'z') continue;

                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 放弃输入,关闭窗口。
        /// </summary>
        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            //if (IsFilePath)
            //{
            //    if (ValidateFilePath() == false)
            //    {
            //        tbxPrompt2.Text = "文件名中不能包含:\\/:*\"<>|";
            //        return;
            //    }
            //}

            this.DialogResult = false;
            this.Close();
        }

        /// <summary>
        /// 回车键完成输入;Esc键放弃输入。
        /// </summary>
        private void tbxInput_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                btnOK_Click(sender, e);
            }
            else if (e.Key == Key.Escape)
            {
                btnCancel_Click(sender, e);
            }
        }

        /// <summary>
        /// 窗口载入时自动对焦,便于立即开始输入。
        /// </summary>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            tbxInput.Focus();
        }
    }
}