// /*****************************************************
// (c)2008-2013 Copy right www.Gboxt.com
// ×÷Õß:bull2
// ¹¤³Ì:CodeRefactor-Agebull.CodeRefactor.CodeAnalyze
// ½¨Á¢:2014-11-10
// ÐÞ¸Ä:2014-11-10
// *****************************************************/

/*
 ·ÂRazorÓï·¨ÌÇ
 ***@Óï·¨ÌÇµÄÇ°µ¼³öÏÖ,±ØÐëÊÇ@Óë¹æ¶¨×Ö·û,²»ÔÊÐí³öÏÖ¿Õ¸ñ
 ***Åä¶Ô(³É¶ÔÆ¥Åä),Ê¹ÓÃÏÈ½øÏÈ³öµÄ·½Ê½Æ¥Åä,Óï·¨¿é»ò±äÁ¿ÖÐµÄC#×¢ÊÍÓë×Ö·û´®ÖÐµÄÄÚÈÝ²»²ÎÓëÆ¥Åä
 * Àý:
 @{
    if(true)
    {
        var txt="ÕâÀïµÄ}²»²ÎÓëÆ¥Åä";//Õâ¸ö×¢ÊÍµÄ{{Ò²²»²ÎÓëÆ¥Åä
    }
 }
 <input type='text'/>
 *´ËÊ±@{´úÂë¿éµÄµÄ½áÊøÔÚµÚÁùÐÐµÄ}´¦,½âÎö½á¹û´úÂëÀàËÆÈçÏÂ
    if(true)
    {
        var txt="ÕâÀïµÄ}²»²ÎÓëÆ¥Åä";//Õâ¸ö×¢ÊÍµÄ{{Ò²²»²ÎÓëÆ¥Åä
    }
    Append(" <input type='text'/>");
 [Óï·¨¿é]
 1 @-...:µ¥ÐÐ´úÂë
 2 @{...}:´óÀ¨ºÅÅä¶ÔÄÚ²¿µÄÄÚÈÝµÄ½âÎöÎªÒ»°ã´úÂë,ÇÒÎÞ@×ª»»Êä³ö,ÈçÐèÒªÊä³öÊ¹ÓÃÄÚ²¿µÄAppend·½·¨
 *Àý:
 @{
    Append("123");
 }
 <input type='text'/>
 *½á¹û´úÂë(¿É±àÒëÍ¨¹ýµÄ)
    Append("123");
    Append(" <input type='text'/>");
    *Àý:
 @{
    @:123
 }
 <input type='text'/>
 *½á¹û´úÂë(ÎÞ·¨±àÒëÍ¨¹ýµÄ)
    @:123
    Append(" <input type='text'/>");

 3 @¿ØÖÆ¹Ø¼ü×Ö:
    ¿ØÖÆ¹Ø¼ü×ÖÖ¸if else for foreach switch,
    °´C#Óï·¨ÒªÇó,³ýÎÞºóifµÄelseÍâ,Æ¥Åäµ½Ð¡À¨ºÅÅä¶Ô,elseºóÔÊÐí³öÏÖµÄifÒ²Ê¹ÓÃÕâÖÖÆ¥Åä(ºóÐøÄÚÈÝÔÚÆ¥ÅäÖ®ºó)
    *Èç¹ûºó·½»¹ÓÐ·¶Î§ÄÚµÄ´úÂëÊ±,
        A ½Ó{È»ºóÔÚÐÂÐÐ¿ªÊ¼Ê¹ÓÃ@{...}·½Ê½
        B ½Ó{+@Ö®ºóµÄÄÚÈÝ¶¼ÊÇÆÕÍ¨´úÂë,Ö±µ½³öÏÖµ¥¶ÀÒ»ÐÐµÄÓÐÇÒÖ»ÓÐÁ½¸ö@@µÄµØ·½½áÊø´úÂë¿é
    *Èç¹ûÒªÃ÷È·Ö¸Ã÷ºó·½ÄÚÈÝÔÚ¿ØÖÆÆ÷µÄ·¶Î§,
        Cºó·½¸úÒ»¸ö{±íÊ¾·¶Î§¿ªÊ¼,A·½Ê½Óë´ËÏàÍ¬
        D½áÊøÎª³É¶ÔÆ¥ÅäµÄ[»»ÐÐ+@+}+»»ÐÐ],¼´ÄÚÈÝÖÐÔÙ´Î³öÏÖÖ¸¶¨·¶Î§·½Ê½µÄ¿ØÖÆ¿éÊ±,°´¶ÑÕ»·½Ê½Æ¥Åä
    *Èç¹û²»Ö¸Ã÷¿ØÖÆÆ÷µÄ·¶Î§,ÄÚÈÝ·¶Î§ÔÚÏÂÒ»¸ö´úÂë¿é³öÏÖÇ°½áÊø(ÑÏÖØ²»½¨Òé´Ë·½·¨)
    *Àý:
 @if(true)
 {@
    Append("123");
@@
    <input type='text'/>
    <input type='text'/>
 @}
 *½á¹û´úÂë(¿É±àÒëÍ¨¹ýµÄ)
 if(true)
 {
    Append("123");
    Append(@" <input type='text'/>
    <input type='text'/>");
 }
    *Àý:
 @if(true)
 <input type='text'/>
 <input type='text'/>
 @else
 <input type='text'/>
 @{ var a = 10;}
 *½á¹û´úÂë(¿É±àÒëÍ¨¹ýµÄ)
 if(true)
    Append(@" <input type='text'/>
    <input type='text'/>");
 else
    Append(@" <input type='text'/>
    <input type='text'/>");
 var a = 10;
    *Àý:
 @if(true)
 <input type='text'/>
 <input type='text'/>
 @if(true)
 <input type='text'/>
 <input type='text'/>
 @else
 <input type='text'/>
 @{ var a = 10;}
 *½á¹û´úÂë(¿É±àÒëÍ¨¹ýµÄ)
 if(true)
 {
    Append(@" <input type='text'/>
    <input type='text'/>");
     if(true)
     {
        Append(@" <input type='text'/>
        <input type='text'/>");
     }
     else
     {
     Append(@" <input type='text'/>
        <input type='text'/>");
     }
 }
 var a = 10;
 [±äÁ¿]
 1 ÊôÐÔ»ò×Ö¶ÎÊä³ö
 @Ãû³Æ.Ãû³Æ:
    Ãû³ÆÊÇ×ÖÄ¸Êý×ÖÏÂ»®Ïß×é³ÉµÄ°üÀ¨¸÷ÖÖÎÄ×Ö(µ¥´ÊÒÔASCII128ÄÚµÄ·Ç×ÖÄ¸Êý×ÖÏÂ»®ÏßµÄ×Ö·û½áÊø),ºó·½¿ÉÒÔÁ¬½Ó.×Ö·û(ÔÊÐí.Ç°ºó¼ä¸ô¿Õ°×)ÒÔ·ÃÎÊÊôÐÔ»ò×Ö¶Î
    ºó·½µÄ()µÄ·½·¨µ÷ÓÃ²»Ö§³Ö,ÐèÒª·½·¨·µ»ØÖµ,ÇëÓÃ@()Ä£Ê½
    *Àý:
    <input type='@name.Length'/>
    *½á¹û´úÂë(¿É±àÒëÍ¨¹ýµÄ)
     Append(@"    <input type='{0}'/>",name.Length);
 2 ÄÚÈÝÊä³ö
   @():Ð¡À¨ºÅÅä¶ÔÖÐµÄÄÚÈÝÖ±½Ó½âÎöÎª±äÁ¿Êä³ö(ËùÓÐÒ»¸ö±äÁ¿Êä³ö\·½·¨µ÷ÓÃ\Ç¿ÖÆ×ª»»¾ù¿ÉÓÃ),ÈçÎÞ·µ»ØÖµµÄ·½·¨µ÷ÓÃ»áµ¼ÖÂ±àÒë´íÎó
 *Àý:
    <input type='@(name.ToString())'/>
    *½á¹û´úÂë(¿É±àÒëÍ¨¹ýµÄ)
     Append(@"    <input type='{0}'/>",name.ToString());
 ÆÕÍ¨Êä³ö
 1Á½¸ö@,Êä³ö@×Ö·û
 2 @Ö®ºó²»·ûºÏÒÔÉÏÔ­ÔòµÄ,@×÷ÎªÆÕÍ¨Êä³ö,¼´Ê¹@+¿Õ°×+{Ò²ÊÇÈç´Ë
 3 ÆäËü²»·ûºÏÒÔÉÏÓï·¨ÌÇµÄÄÚÈÝ
 4 ´úÂë¿éÖ®ºóµÄ»»ÐÐ²»Êä³ö
 5 @*...*@Îª×¢ÊÍ,²»Êä³ö
 ·À´í½¨Òé
 1 ·½·¨µ÷ÓÃ·µ»ØÖµµÄÊä³ö,±ØÐëÊ¹ÓÃ@(·½·¨())·½Ê½
 2 ·½·¨ÔÚ¿ØÖÆ¿éÖÐ,Èç¹ûÓÐ[»»ÐÐ+@+}+»»ÐÐ]»ò[»»ÐÐ+@+}+»»ÐÐ]µÄÆÕÍ¨Êä³öÊ±,ÇëÓÃ@@{
 3 Ê¹ÓÃÊôÐÔ»ò×Ö¶ÎÊä³öÊ±,Èç¹ûºó·½Á¬½Ó³Éµ¥´ÊµÄÈÝÒ×Ôì³ÉÆçÒå,ÇëÊ¹ÓÃ@()·½Ê½,Èç:
    Àý×ÓA 
    ÓÐ±äÁ¿ nameÇÒÖµÎª123,ÏëÒªÊä³öµÄ½á¹ûÎª str123456,Ð´·¨Îªstring str@(name)456,
    ÈçÐ´³Éstr@name456,½«¿ÉÄÜÊ¹ÓÃÒÑ¶¨ÒåµÄ±äÁ¿name456Êä³ö»òÔËÐÐÊ±ÒòÎªÃ»ÓÐÕâ¸ö±äÁ¿³ö´í
    Àý×ÓB
    ÓÐ±äÁ¿ nameÇÒÖµÎªid,ÏëÒªÊä³öµÄ½á¹ûÎª str_id_name,Ð´·¨Îªstring str_@(name)_name,
    ÈçÐ´³Éstr_@name_name,½«¿ÉÄÜÊ¹ÓÃÒÑ¶¨ÒåµÄ±äÁ¿name_nameÊä³ö»òÔËÐÐÊ±ÒòÎªÃ»ÓÐÕâ¸ö±äÁ¿³ö´í
*/
#region ÒýÓÃ

using System.Text;

#endregion

namespace Agebull.EntityModel.RobotCoder.CodeTemplate.CSharp
{
    /// <summary>
    ///     ´úÂëµ¥Ôª·ÖÎöÆ÷
    /// </summary>
    public sealed class TemplateParse : TemplateParseBase
    {

        #region ·ÖÎöÎÄ±¾

        /// <summary>
        /// Éú³É´úÂë
        /// </summary>
        /// <returns></returns>
        protected override string BuildCode()
        {
            StringBuilder codeElement = new StringBuilder();
            codeElement.AppendLine($"public string {Config.Name}()");
            codeElement.AppendLine("{");
            codeElement.AppendLine("    StringBuilder strResult = new StringBuilder();");
            //foreach (var line in Codes)
            //{
            //    codeElement.AppendLine(line);
            //}
            codeElement.AppendLine("    return strResult.ToString();");
            codeElement.AppendLine("}");
            return codeElement.ToString();
        }

        #endregion


        #region ºÏ²¢µ¥´Ê

        ///// <summary>
        /////     ºÏ²¢ÆÕÍ¨ÎÄ±¾ÄÚÈÝ¿é
        ///// </summary>
        ///// <param name="curElement">ÒªºÏ²¢²¿·Ö</param>
        //protected override void MergeContentElement(WordElement curElement)
        //{
        //    if (curElement == null)
        //        return;
        //    if (curElement.Element.IsPunctuate)
        //    {
        //        switch (curElement.Char)
        //        {
        //            case '{':
        //            case '}':
        //            case '\"':
        //                curElement.Append(curElement.Element.End, curElement.Char);
        //                break;
        //        }
        //    }
        //    if (contentElement == null)
        //        contentElement = curElement;
        //    else
        //        contentElement.Merge(curElement);
        //}

        //        /// <summary>
        //        /// ÒÔµ±Ç°ÓïÑÔµÄ´úÂë·½Ê½µÄÆÕÍ¨ÎÄ±¾ÄÚÈÝÆ´½ÓµÄ´úÂë
        //        /// </summary>
        //        /// <param name="content">ÆÕÍ¨ÄÚÈÝÎÄ±¾</param>
        //        /// <returns></returns>
        //        protected override string AppendContentCode(string content)
        //        {
        //            return $@"{CodeSpace}strResult.Append($@""
        //{content}"");";
        //        }

        /// <summary>
        /// ¼ì²é±êµã´òÍ·µÄ´úÂë¿é
        /// </summary>
        /// <returns></returns>
        protected override bool CheckPunctuateStartCode()
        {
            if (WordElements[CurWordIndex].Char == '}')
            {
                var codeElement = new AnalyzeElement();
                return CheckIsCodeBlockEnd(codeElement);
            }
            return base.CheckPunctuateStartCode();
        }

        /// <summary>
        /// ¼ì²éµ¥´Ê´òÍ·µÄ´úÂë¿é
        /// </summary>
        /// <returns></returns>
        protected override bool CheckWordStartCode()
        {
            var codeElement = new AnalyzeElement();
            switch (WordElements[CurWordIndex].RealWord)
            {
                case "if":
                case "for":
                case "foreach":
                case "switch":
                    codeElement.ItemRace = CodeItemRace.Range;
                    codeElement.Append(WordElements[CurWordIndex]);
                    FindCouple(codeElement, '(', ')', true, true);
                    TryGoNextWithWord(codeElement, "{", true);
                    CheckMulitCode(codeElement);
                    break;
                case "else":
                    //ÊÔÍ¼²éÕÒºóÐøµÄif
                    codeElement.ItemRace = CodeItemRace.Range;
                    codeElement.Append(WordElements[CurWordIndex]);
                    if (TryGoNextWithWord(codeElement, "if", true))
                    {
                        FindCouple(codeElement, '(', ')', true, true);
                    }
                    TryGoNextWithWord(codeElement, "{", true);
                    CheckMulitCode(codeElement);
                    break;
                default:
                    FindVariable(codeElement, '.');
                    break;
            }
            JoinCode(codeElement);
            return true;
        }

        ///// <summary>
        ///// ×éºÏ´úÂë
        ///// </summary>
        ///// <param name="isCodeBlock"></param>
        ///// <param name="codeElement"></param>
        //void JoinCode(bool isCodeBlock, WordElement codeElement)
        //{
        //    if (contentElement != null)
        //    {
        //        if (isCodeBlock)
        //        {
        //            AppendContentCode(contentElement);
        //            contentElement = null;
        //        }
        //        else
        //        {
        //            contentElement.Append(codeElement.Element.End, $"{{{codeElement.RealWord.Trim()}}}");
        //        }
        //    }
        //    else if (!isCodeBlock)
        //    {
        //        Codes.Add($"strResult.Append({codeElement.RealWord.Trim()});");
        //    }
        //    if (isCodeBlock && codeElement != null)
        //    {
        //        Codes.Add(codeElement.RealWord);
        //    }
        //    if (CurWordIndex < this.WordElements.Count && this.WordElements[CurWordIndex].Element.IsSpace)
        //    {
        //        CurWordIndex--; //¿Õ°×»¹»ØÈ¥
        //    }
        //}



        #endregion

        #region ÌØÊâµ¥ÔªµÄ×éºÏ

        /// <summary>
        ///     ´¦Àíµ±Ç°ÓïÑÔÄÚÈÝ
        /// </summary>
        /// <param name="codeElement">ÓïÑÔ½Úµã</param>
        /// <param name="preChar"></param>
        public override void MergeLanWord(AnalyzeElement codeElement, ref char preChar)
        {
            WordElement cur = WordElements[CurWordIndex];
            codeElement.Append(cur);
            if (!cur.IsPunctuate)
            {
                preChar = '\0';
                return;
            }
            switch (cur.Char)
            {
                #region ×¢ÊÍ

                case '/':
                    if (preChar != '/')
                    {
                        preChar = '/';
                        return;
                    }
                    MergeSinleRem(codeElement);
                    break;
                case '*':
                    if (preChar == '/')
                    {
                        MergeMulitRem(codeElement);
                    }
                    break;

                #endregion

                #region ×Ö·û´®

                case '@':
                    preChar = '@';
                    return;
                case '\"':
                    if (preChar == '@')
                    {
                        var block = codeElement.Elements[codeElement.Elements.Count - 2];
                        block.Append(cur);
                        codeElement.Elements.RemoveAt(codeElement.Elements.Count - 1);
                        MergeMulitString(block);
                    }
                    else
                    {
                        MergeString(cur, '\"');
                    }
                    break;
                case '\'':
                    MergeString(cur, '\'');
                    break;

                    #endregion
            }
            preChar = '\0';
        }


        /// <summary>
        ///     ºÏ²¢¶àÐÐÎÄ±¾
        /// </summary>
        /// <param name="codeElement"></param>
        private void MergeMulitString(WordElement codeElement)
        {
            bool isShift = false;
            for (CurWordIndex++; CurWordIndex < WordElements.Count; CurWordIndex++)
            {
                WordElement curElement = WordElements[CurWordIndex];
                if (curElement.Char == '\"')
                {
                    isShift = !isShift;
                    codeElement.Append(curElement);
                    continue;
                }
                if (isShift)
                {
                    --CurWordIndex;//»ØÍË
                    return;
                }
                codeElement.Append(curElement);
            }
        }

        /// <summary>
        ///     ºÏ²¢¶àÐÐ×¢ÊÍ
        /// </summary>
        /// <param name="codeElement"></param>
        private void MergeMulitRem(AnalyzeElement codeElement)
        {
            var last = codeElement.Elements[codeElement.Elements.Count - 1];
            codeElement.Elements.RemoveAt(codeElement.Elements.Count - 1);
            var element = codeElement.Elements[codeElement.Elements.Count - 1];
            element.ItemRace = CodeItemRace.Assist;
            element.ItemFamily = CodeItemFamily.Rem;
            element.Word += last.Word;
            codeElement.CurrentElement = element;

            bool isShift = false;
            for (CurWordIndex++; CurWordIndex < WordElements.Count; CurWordIndex++)
            {
                WordElement curElement = WordElements[CurWordIndex];
                element.Word += curElement.RealWord;
                if (isShift && curElement.Char == '/')//×¢ÊÍ½áÊø
                {
                    return;
                }
                isShift = curElement.Char == '*';
            }
        }
        /// <summary>
        ///     ºÏ²¢×¢ÊÍ
        /// </summary>
        /// <param name="codeElement"></param>
        private void MergeSinleRem(AnalyzeElement codeElement)
        {
            var last = codeElement.Elements[codeElement.Elements.Count - 1];
            codeElement.Elements.RemoveAt(codeElement.Elements.Count - 1);
            var element = codeElement.Elements[codeElement.Elements.Count - 1];
            element.ItemRace = CodeItemRace.Assist;
            element.ItemFamily = CodeItemFamily.Rem;
            element.Word += last.Word;
            codeElement.CurrentElement = element;

            for (CurWordIndex++; CurWordIndex < WordElements.Count; CurWordIndex++)
            {
                if (WordElements[CurWordIndex].IsLine) //ÐÐÒÑ½áÊø
                {
                    --CurWordIndex; //»ØÍË
                    return;
                }
                element.Word += WordElements[CurWordIndex].RealWord;
            }
        }

        #endregion
    }
}
