using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CobXmlSupport
{
    public class IndexState
    {

        private char[] splitChars={'#'};
        private string latestStr;
        private string wrkString;
        private string wrkSectStr;
        private string wrkVarStr;
        private Dictionary<string, string> indexes;
        private List<CobRow> rows;
        private bool inOut;
        private string extraParam;

        public Dictionary<string, string> Indexes
        {
            get { return indexes; }
            //set { indexes = value; }
        }

        public string ExtraParam
        {
            // private variable to use from method which need temporary extra
            // method using it responsible for cleaning it
            get { return extraParam; }
        }

        public IndexState(Dictionary<string, string> varIndex, List<CobRow> xrows, bool bin=true)
        {
            latestStr = "";
            indexes = varIndex;
            wrkSectStr = "";
            wrkVarStr = "";
            rows = xrows;
            inOut = bin; // "IN" == true "OUT" == false
        }

        public string ProcStr
        {
            get
            {                     
                string repInfoStr = "\r\n      * ==================== 88 - variabler =============* ";
                repInfoStr += wrkVarStr;
                repInfoStr +=       "\r\n      * ==================== 88 - variabler =============* \r\n";
                repInfoStr += wrkSectStr;
                return repInfoStr;
            }
        }

        public string PresentStrings(string indexlist) {
            string codeString="";
            wrkString = indexlist;
            if(!latestStr.Equals(wrkString)){
                codeString=analyseDiff();
            }
            return codeString;
        }

        private string analyseDiff()
        {
            string genCode = "";
            string[] latestList=latestStr.Split(splitChars), 
                wrkList=wrkString.Split(splitChars);
            if (latestList.Length > 0)
            {
                for(int i=latestList.Length-1;i>-1;i--){
                    if (!wrkList.Contains(latestList[i]) && latestList[i].Length>0)
                    {
                        genCode+="\r\n           END-PERFORM";
                    }
                }
            }
            if (wrkList.Length > 0)
            {
                for(int i=wrkList.Length-1;i>-1;i--){
                    if(!latestList.Contains(wrkList[i])){
                        string countVar = "";
                        string tagName = "";
                        int occNum = 0;
                        if (!wrkList[i].Equals(""))
                        {
                            string chosenKey = indexes.FirstOrDefault(x => x.Value == wrkList[i]).Key;  // indexes = <FieldName , FieldIndex> search FieldName from present FieldIndex
                            countVar = rows.First(x => x.FieldName == chosenKey).CountIn; // from cobrows find "Count In"-variable for given FieldName
                            tagName = rows.First(x => x.FieldName == chosenKey).TagName; // from cobrows find "xmltag" for given FieldName
                            occNum = rows.First(x => x.FieldName == chosenKey).occNum;
                            string inLst = "";
                            int j = i + 1;

                            //genCode += "\r\n           *>" + wrkString;
                            if (inOut) // When moving to cobol xml structure 
                            {
                                if (occNum.ToString() != S.ettingMaxOcc && occNum!=0)
                                {
                                    genCode += "\r\n           MOVE " + occNum.ToString() + " TO " + countVar;
                                }
                                else
                                {
                                    genCode += "\r\n           MOVE " + S.ettingMaxOcc + " TO " + countVar;
                                }
                                // genCode += "\r\n           MOVE 0 TO " + countVar;
                                while (wrkList.Length > j)
                                {
                                    if (inLst.Length == 0)
                                    {
                                        inLst = "\r\n                       " + wrkList[j];
                                    }
                                    else
                                    {
                                        inLst = "\r\n                       " + wrkList[j] +"," +inLst;
                                    }
                                    j++;
                                }
                                if (inLst.Length > 0)
                                {
                                    genCode += "\r\n                       ( " + inLst + " )";
                                }
                                inLst = "";
                            }


                            genCode += "\r\n           PERFORM VARYING " + wrkList[i] + " FROM 1 BY 1";
                            //genCode += "\r\n               UNTIL EXIT ";
                            //genCode += "\r\n               UNTIL " + wrkList[i] + " > " + countVar;
                            genCode += "\r\n               UNTIL " + wrkList[i] + " > ";

                            extraParam = countVar;
                            j = i + 1;
                            while (wrkList.Length > j)
                            {
                                if (inLst.Length == 0)
                                {
                                    inLst = "\r\n                          " + wrkList[j];
                                }
                                else
                                {
                                    inLst = "\r\n                         " + wrkList[j] + "," + inLst;
                                }
                                j++;
                            }
                            if (inLst.Length > 0)
                            {
                                extraParam +=  "\r\n                       ( " + inLst + " )";
                            }
                            genCode += extraParam;

                            if (inOut)
                            {
                                string tmpCheckVar="";
                                genCode += "\r\n               PERFORM  " + createReferenceSections(tagName,"NXT-",out tmpCheckVar);
                                genCode += "\r\n               IF " + tmpCheckVar;
                                genCode += "\r\n                   SUBTRACT 1 FROM " + wrkList[i];
                                genCode += "\r\n                   MOVE " + wrkList[i] + " TO " + countVar;
                                if (inLst.Length > 0)
                                {
                                    genCode +=   "\r\n                       ( " + inLst + " )";
                                }
                                genCode += "\r\n                   EXIT PERFORM";
                                genCode += "\r\n               END-IF";
                            }

                        }
                    }
                }
            }
            latestStr = wrkString;
            return genCode;
        }

        private string createReferenceSections(string tagName, string procPrefix,out string missIdent)
        {
            missIdent=tagName.Replace("\"","").Replace(":","");
            string tmpProcName = procPrefix + missIdent;
            if(!wrkSectStr.Contains(tmpProcName)){
                wrkSectStr += "\r\n      *>-------------------- READ SECTION ---------------*" + tmpProcName;
                wrkSectStr += "\r\n      * Den här sektionen används för att positionera ";
                wrkSectStr += "\r\n      * datat när den genererade xml-proceduren körs";
                wrkSectStr += "\r\n      *--------------------- READ SECTION ---------------*\r\n";
                wrkSectStr += "\r\n       " + tmpProcName + " SECTION.";
                wrkSectStr += "\r\n      *    READ NEXT" + tagName;
                wrkSectStr += "\r\n           IF POST-SAKNAS";
                wrkSectStr += "\r\n               SET " + "NO-"+missIdent + " TO TRUE";
                wrkSectStr += "\r\n           END-IF";
                wrkSectStr += "\r\n           .";
                wrkSectStr += "\r\n       "+tmpProcName+"-EX.";
                wrkSectStr += "\r\n           EXIT.\r\n";

                wrkVarStr += "\r\n       01 "+missIdent+"-X           PIC X VALUE SPACE.";
                wrkVarStr += "\r\n           88 " + "NO-" + missIdent + "     VALUE \"X\".";
                wrkVarStr += "\r\n           88 " + missIdent + "-OK  VALUE SPACE.";
                missIdent = "NO-" + missIdent;
            }
            return tmpProcName;
        }

    }
}
