using Microsoft.Office.Interop.Word;
using OfficeAppHelp.Help;
using OfficeAppHelp.Word;
using QuestionSwapDoc.SwapQuestionModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Range = Microsoft.Office.Interop.Word.Range;

namespace QuestionSwapDoc
{
    /// <summary>
    /// 输出为试题
    /// </summary>
    public class SwapQuestion
    {
        //判断题的答案解析字符串
        public static readonly string[] PanDtTrue = new string[] { "对", "正确", "√", "✔", };
        public static readonly string[] PanDtFlase = new string[] { "错", "错误", "×", "✘", };
        //选择题的选项前缀字符串
        public static readonly string[] XuanXianQianZui = new string[] { "A.", "B.", "C.", "D.", "E.", "F.", "G.", "H.", "I.", "J.", "K." };

        /// <summary>
        /// 得到文档解析出来的试题
        /// </summary>
        /// <param name="fileName">所有可以用word打开的文件的全路径【如："D:\word.docx"】</param>
        /// <param name="xmlDirectory">xml文件文件夹（文件名称随机方式）【为空为文档名加parse，如："D:\wordparse"】</param>
        /// <param name="linkDirectory">html关联文件文件夹（文件名称md5方式）【为空为文档名加parse，如："D:\wordparse"】</param>
        /// <param name="imgLinkLeftPath">html中img中src的前缀【为空：[img src='md5.png']；假如为‘imgfiles’：[img src='imgfiles\md5.png']】</param>
        /// <param name="queTypeString">题型字符串。用来告诉解析器那些字符串属于那些题型。</param>
        /// <returns></returns>
        public static QueDoc GetQue(string fileName, string xmlDirectory = "", string linkDirectory = "", string imgLinkLeftPath = "", QueTypeString queTypeString = null)
        {
            if (queTypeString == null)
                queTypeString = new QueTypeString();
            if (queTypeString.XuanZheStrings == null)
                queTypeString.XuanZheStrings = new string[] { };
            if (queTypeString.PanDuanStrings == null)
                queTypeString.PanDuanStrings = new string[] { };

            var p1 = Path.GetDirectoryName(fileName);//D:\
            var p2 = Path.GetFileNameWithoutExtension(fileName) + "parse";//wordparse
            var p3 = Path.Combine(p1, p2);//D:\wordparse
            if (string.IsNullOrWhiteSpace(xmlDirectory))
                xmlDirectory = p3;
            if (string.IsNullOrWhiteSpace(linkDirectory))
                linkDirectory = p3;

            WordApp wordApp = null;
            try
            {
                wordApp = new WordApp(fileName, true, "123");
                return GetQue(wordApp, xmlDirectory, linkDirectory, imgLinkLeftPath, queTypeString);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                wordApp?.Close();
            }
        }
        private static QueDoc GetQue(WordApp wordApp, string xmlDirectory, string linkDirectory, string imgLinkLeftPath, QueTypeString queTypeString)
        {
            QueDoc queDoc = new QueDoc();

            //浮动元素警告
            var wiWar = wordApp.Doc.Content.GetNotWrapInlineShape()
                .Select(o => o.Anchor.GetPageNumberStart())
                .GroupBy(o => o)
                .Select(o => $"第{o.Key}页，有{o.Count()}个非“嵌入型”元素，可能存在解析不出来的风险。");
            queDoc.Warning.AddRange(wiWar);
            //空文档错误
            if (wordApp.Doc.Content.IsNull())
            {
                queDoc.Warning.Add("这是一个空文档，无法解析为试题。");
                return queDoc;
            }
            //tab警告
            if (wordApp.Doc.Content.FindFirst(WordApp.Find_Tab, true) != null)
                queDoc.Warning.Add("文档中发现[Tab]按键，可能会影响解析布局。");

            DisposeListFormat(wordApp.Doc);
            wordApp.Doc.Content.SetColor(WdColor.wdColorBlack);
            wordApp.Doc.Content.InsertParagraphAfter();
            wordApp.Doc.Content.Replace(WordApp.Find_BlankRow, WordApp.Find_Paragraph);
            wordApp.Doc.Content.Replace(WordApp.Find_Tab, "    ");//为了兼容性
            wordApp.Doc.Content.CharacterWidth = WdCharacterWidth.wdWidthHalfWidth;//全文档改为半角


            //上一行是否为空行
            bool isTopLine = true;
            //题型
            string queType = string.Empty;
            //难易程度(1容易 2较易 3中等 4较难 5困难)
            int? queDiff = null;
            //题的标记信息
            string queData = string.Empty;
            //解析标识
            QueItemType queParseItem = QueItemType.空行;
            //当前选项的索引
            int danXuanXian = 0;

            List<QueItem> ques = new List<QueItem>();
            QueItem que = null;

            foreach (Paragraph paragraph in wordApp.Doc.Paragraphs)
            {
                Range range = paragraph.Range;

                //当前行 是否为空行
                bool isInLine = range.IsNullOrSpace();

                //连续空行
                if (isInLine && isTopLine)
                {
                    //跳过
                    isTopLine = isInLine;
                    que = null;
                    continue;
                }
                //空行
                else if (isInLine && !isTopLine)
                {
                    //标记结尾
                    SetEnd(ref que, queParseItem, range.Start, queTypeString);
                    if (que != null)
                    {
                        ques.Add(que);
                        que = null;
                    }

                    queParseItem = QueItemType.空行;
                    isTopLine = isInLine;
                    continue;
                }
                //新的内容（题干或标记）开始
                else if (!isInLine && isTopLine)
                {
                    //题干或者标记
                    string tgOrbj = range.Text.Trim();

                    //1.对标记处理
                    if (tgOrbj.StartsWith("题型：") || tgOrbj.StartsWith("题型:") || tgOrbj.StartsWith("【题型】"))
                    {
                        if (tgOrbj.StartsWith("【题型】"))
                            queType = tgOrbj.Substring(4).Trim();
                        else
                            queType = tgOrbj.Substring(3).Trim();

                        isTopLine = true;
                        continue;
                    }
                    else if (tgOrbj.StartsWith("难易程度：") || tgOrbj.StartsWith("难易程度:") || tgOrbj.StartsWith("【难易程度】"))
                    {
                        if (tgOrbj.StartsWith("【难易程度】"))
                            queDiff = QueItem.ToNanYiInt(tgOrbj.Substring(6).Trim());
                        else
                            queDiff = QueItem.ToNanYiInt(tgOrbj.Substring(5).Trim());

                        isTopLine = true;
                        continue;
                    }
                    else if (tgOrbj.StartsWith("【题编码信息】"))
                    {
                        queData = tgOrbj.Substring(7).Base64ToStringTry(out bool tgIsOk);
                        isTopLine = true;
                        continue;
                    }

                    //2.初始化 标记
                    queParseItem = QueItemType.题干;
                    que = new QueItem()
                    {
                        TiXin = queType,
                        NanYi = queDiff,
                    };
                    que.TiRange.Start = range.Start;
                    que.TiGanRange.Start = range.Start;
                    que.Data = queData;
                    queData = string.Empty;
                }
                //正在试题中间
                else if (!isInLine && !isTopLine)
                {
                    string txbj = range.Text.Trim();
                    //是否为选择题
                    bool isXx = queTypeString.XuanZheStrings.Contains(queType);
                    //可能在选项的位置
                    if (isXx && (queParseItem == QueItemType.题干 || queParseItem == QueItemType.选项))
                    {
                        if (queParseItem == QueItemType.题干)
                            danXuanXian = 0;

                        //确定在选项的位置
                        if (txbj.StartsWith(XuanXianQianZui[danXuanXian]))
                        {
                            //给题干标记结束
                            if (que.TiGanRange.End == null)
                                que.TiGanRange.End = range.Start - 1;

                            var r1 = range.FindFirst(XuanXianQianZui[danXuanXian]);

                            queParseItem = QueItemType.选项;
                            danXuanXian++;
                            bool isTop = true;
                            int t = r1.End;
                            while (isTop)
                            {
                                var findRange = range.FindFirst(XuanXianQianZui[danXuanXian]);
                                if (findRange != null)
                                {
                                    Range r2 = wordApp.Doc.Range(t, findRange.Start);
                                    que.XuanXianRanges.Add(new QueItemRange(t, findRange.Start));

                                    t = findRange.End;
                                    danXuanXian++;
                                }
                                else
                                {
                                    Range r2 = wordApp.Doc.Range(t, range.End);
                                    que.XuanXianRanges.Add(new QueItemRange(t, range.End - 1));

                                    isTop = false;
                                }
                            }
                        }
                    }
                    //答案
                    if (txbj.StartsWith("答案：") || txbj.StartsWith("答案:") || txbj.StartsWith("【答案】"))
                    {
                        que.DaAnRange.Start = range.FindFirst("答案").End + 1;

                        //标记结尾
                        SetEnd(ref que, queParseItem, range.Start, queTypeString);

                        queParseItem = QueItemType.答案;
                    }
                    //解析
                    else if (txbj.StartsWith("解析：") || txbj.StartsWith("解析:") || txbj.StartsWith("【解析】"))
                    {
                        que.JieXiRange.Start = range.FindFirst("解析").End + 1;

                        //标记结尾
                        SetEnd(ref que, queParseItem, range.Start, queTypeString);

                        queParseItem = QueItemType.解析;
                    }

                }

                //上一行 = 当前行
                isTopLine = isInLine;
            }

            //把定位的标记转为文件
            DocToFile(wordApp.Doc, xmlDirectory, linkDirectory, imgLinkLeftPath, queTypeString, ref ques);

            //选择题的选项为空
            if (ques.Any(o => queTypeString.XuanZheStrings.Contains(o.TiXin) && (o.XuanXianRanges == null || !o.XuanXianRanges.Any())))
                queDoc.Warning.Add("发现有无法解析出选项的选择题，请注意选项的编号是否为字母加点开头，如“A.”。");

            queDoc.QueItems = ques;
            return queDoc;
        }


        /// <summary>
        /// 把定位的标记转为文件
        /// </summary>
        private static void DocToFile(Document Doc, string xmlDirectory, string linkDirectory, string imgLinkLeftPath, QueTypeString queTypeString, ref List<QueItem> ques)
        {
            Directory.CreateDirectory(xmlDirectory);
            Directory.CreateDirectory(linkDirectory);

            foreach (var que in ques)
            {
                //标记所有题的位置
                que.TiAllRange.Start = que.TiRange.Start;
                que.TiAllRange.End = new List<int?>() { que.JieXiRange.End, que.DaAnRange.End, que.TiRange.End }.Max();

                //填充文件
                que.TiAllRange.Fill(Doc, xmlDirectory, linkDirectory, imgLinkLeftPath);
                que.TiRange.Fill(Doc, xmlDirectory, linkDirectory, imgLinkLeftPath);
                que.TiGanRange.Fill(Doc, xmlDirectory, linkDirectory, imgLinkLeftPath);
                que.XuanXianRanges.ForEach(o => o.Fill(Doc, xmlDirectory, linkDirectory, imgLinkLeftPath));

                //是否为选择题
                if (queTypeString.XuanZheStrings.Contains(que.TiXin))
                {
                    que.TiStr = que.TiGanRange.GetRange(Doc)?.Text.RemoveESC().Trim().Replace("  ", " ");
                    que.DaAnRange.FillXx(Doc);
                }
                //是否判断题
                else if (queTypeString.PanDuanStrings.Contains(que.TiXin))
                {
                    que.TiStr = que.TiRange.GetRange(Doc)?.Text.RemoveESC().Trim().Replace("  ", " ");
                    que.DaAnRange.FillPd(Doc, PanDtTrue, PanDtFlase);
                }
                else
                {
                    que.TiStr = que.TiRange.GetRange(Doc)?.Text.RemoveESC().Trim().Replace("  ", " ");
                    que.DaAnRange.Fill(Doc, xmlDirectory, linkDirectory, imgLinkLeftPath);
                }

                que.JieXiRange.Fill(Doc, xmlDirectory, linkDirectory, imgLinkLeftPath);
            }

        }
        /// <summary>
        /// 处理编号
        /// </summary>
        /// <param name="Doc"></param>
        private static void DisposeListFormat(Document Doc)
        {
            //上一行是否为空行
            bool isTopLine = true;

            foreach (Paragraph paragraph in Doc.Paragraphs)
            {
                Range range = paragraph.Range;
                bool isInLine = range.IsNullOrSpace();

                //对题干处理
                //新的内容（题干或标记）开始
                if (!isInLine && isTopLine)
                {
                    //查找编号（标准的）
                    if (!string.IsNullOrEmpty(range.ListFormat.ListString))
                    {
                        //删除题干的编号（标准的）
                        range.ListFormat.RemoveNumbers();
                    }
                    else
                    {
                        //查找编号（非标准的）
                        string txt = range.Text.GetSerialNumber(false);
                        if (!string.IsNullOrEmpty(txt))
                        {
                            Range serialRange = range.FindFirst(txt);
                            //Range serialRange = Doc.Range(range.Start, range.Start + txt.Length);
                            var sss = serialRange.Text;
                            serialRange.Delete();
                        }
                    }
                }

                //上一行 = 当前行
                isTopLine = isInLine;
            }

            //全文编号改为字符串
            Doc.Content.ListFormat.ConvertNumbersToText();

        }
        /// <summary>
        /// 标记结尾
        /// </summary>
        private static void SetEnd(ref QueItem que, QueItemType queParseItem, int rangeStart, QueTypeString queTypeString)
        {
            if (que == null || queParseItem == QueItemType.空行)
                return;

            rangeStart--;

            //标记结尾
            if (queParseItem == QueItemType.题干)
                if (queTypeString.XuanZheStrings.Contains(que.TiXin))//选择题
                {
                    if (que.XuanXianRanges == null || !que.XuanXianRanges.Any())
                        que.TiRange.End = rangeStart;
                    que.TiGanRange.End = rangeStart;
                }
                else
                    que.TiRange.End = rangeStart;
            else if (queParseItem == QueItemType.选项)
                que.DaAnRange.End = rangeStart;
            else if (queParseItem == QueItemType.答案)
                que.DaAnRange.End = rangeStart;
            else if (queParseItem == QueItemType.解析)
                que.JieXiRange.End = rangeStart;

            if (que.TiRange.End == null && queParseItem != QueItemType.题干)
                que.TiRange.End = rangeStart;
        }

    }
}
