/// <summary>
        ///
        /// </summary>
        /// <param name="routeName"></param>
        /// <param name="writeOnBody"></param>
        /// <param name="writeMinified"></param>
        /// <param name="webModeType"></param>
        /// <param name="disableMtnScriptForClasses"></param>
        /// <returns></returns>
        public static String GetRequiredCode(String routeName = null, Boolean writeOnBody = false, Boolean writeMinified = true, WebModeType webModeType = WebModeType.MvcController, Boolean disableMtnScriptForClasses = false)
        {
            var hostUrl = HttpContext.Current.Request.Url.AbsoluteUri;

            hostUrl = hostUrl.Substring(0, hostUrl.LastIndexOf(HttpContext.Current.Request.Url.AbsolutePath)) + HttpContext.Current.Request.ApplicationPath;
            var script = new StringBuilder("");

            if (disableMtnScriptForClasses)
            {
                Utils.Parameter.DisableMtnScriptForClasses = true;
            }

            if (writeOnBody)
            {
                script.AppendFormat("<script type=\"text/javascript\">\n{0}</script>",
                                    ScriptProcessorEngine.GetStartScriptCode(false, writeMinified));
            }
            else
            {
                string scriptName = ((!Utils.Parameter.UseAjaxExtension && webModeType == WebModeType.MvcController)
                                         ? "mtnlibrary{0}/"
                                         : "mtnlibrary{0}." + Utils.Parameter.AjaxExtension);
                scriptName = string.Format(scriptName, writeMinified ? (!Utils.Parameter.UseAjaxExtension?"-":".") + "min" : "");
                script.AppendFormat(
                    "<script language=\"Javascript\" type=\"text/javascript\" src=\"{0}/{1}{2}\"></script>",
                    (hostUrl.EndsWith("/") ? hostUrl.Substring(0, hostUrl.Length - 1) : hostUrl), routeName.IsNullOrWhiteSpaceMtn() ? "" : routeName + "/", scriptName);
            }
            return(script.ToString());
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="item"></param>
        /// <param name="modeType"></param>
        /// <param name="scriptProcessorType"></param>
        /// <returns></returns>
        public static ScriptProcessorEngine CreateInstance(AjaxClassItem item, WebModeType modeType = WebModeType.MvcController, ScriptProcessorType?scriptProcessorType = null)
        {
            var scriptInstance = new ScriptProcessorEngine(item, modeType, scriptProcessorType);

            return(scriptInstance);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="routeName"></param>
        /// <param name="classList"></param>
        /// <param name="methodList"></param>
        /// <param name="writeOnBody"></param>
        /// <param name="writeMinified"></param>
        /// <param name="scriptProcessorType"></param>
        /// <param name="webModeType"></param>
        /// <param name="isDeferScript"></param>
        /// <param name="isAsync"></param>
        /// <param name="hashTag"></param>
        /// <param name="exportFile"></param>
        /// <param name="virtualPath"></param>
        /// <param name="useTraditionalParameterForm"> </param>
        /// <returns></returns>
        public static string GetScriptCode(String routeName        = null, String classList = null, String methodList = null, Boolean writeOnBody = false,
                                           Boolean writeMinified   = true, ScriptProcessorType?scriptProcessorType    = null,
                                           WebModeType webModeType = WebModeType.MvcController, Boolean isDeferScript = false,
                                           Boolean isAsync         = false, String hashTag = null, Boolean exportFile = false, String virtualPath = "", Boolean useTraditionalParameterForm = false)
        {
            if (writeMinified == false && Utils.Parameter.DisableAjaxDebug)
            {
                return("Ajax debug is disabled on server");
            }

            var script = new StringBuilder();

            if (routeName.IsNullOrWhiteSpaceMtn())
            {
                routeName = Config.RouteCollection.FirstOrDefault();
            }

            var    scriptProcessorTag = (scriptProcessorType.HasValue ? scriptProcessorType.Value.ToString().ToLower().Md5Mtn(true) : "");
            string hashtag            = hashTag.IsNullOrWhiteSpaceMtn() ? (writeMinified ? WriteMinifiedMd5 : WriteUnMinifiedMd5) + scriptProcessorTag + (useTraditionalParameterForm?"useTraditionalParameterForm".Md5Mtn(true):"") : hashTag;
            var    names = new StringBuilder();

            StringBuilder[] scriptCache = { new StringBuilder("") };
            if (hashTag.IsNullOrWhiteSpaceMtn())
            {
                if (classList.IsNullOrWhiteSpaceMtn() == false)
                {
                    foreach (var cname in classList.SplitMtn(",").OrderBy(x => x))
                    {
                        names.Append(cname.ToLowerInvariant());
                    }
                    hashtag += names.ToString().Md5Mtn(true);
                }
                else
                {
                    var list = Config.AjaxScriptCollection;
                    foreach (var ajaxClass in list.Select(x => x.Value))
                    {
                        names.Append(ajaxClass.Key);
                    }
                    ;
                    hashtag += names.ToString();
                }

                if (methodList.IsNullOrWhiteSpaceMtn() == false)
                {
                    foreach (var cname in methodList.SplitMtn(",").OrderBy(x => x))
                    {
                        names.Append(cname);
                    }
                    hashtag += names.ToString().Md5Mtn(true);
                }
            }

            if (Cache.Instance.ContainsKey(MtnAjaxCacheType.AjaxScriptMethod, hashtag) == false)
            {
                var listAuxFunctions = new List <string>();
                if (classList.IsNullOrWhiteSpaceMtn() == false)
                {
                    var listClass = from ajx in Config.AjaxScriptCollection
                                    join ajxCReq in classList.SplitMtn(",").OrderBy(x => x).ToList()
                                    on ajx.Key equals ajxCReq.ToLowerInvariant().Md5Mtn(true)
                                    select ajx.Value;

                    Parallel.ForEach(listClass, (ajaxClass, state) =>
                    {
                        var localAjaxClass = ajaxClass;
                        var ajaxClassItem  = Config.AjaxClassItemCollection.Where(x => x.Key == localAjaxClass.AjaxClassKey).Select(x => x.Value).FirstOrDefault();
                        if (ajaxClassItem == null)
                        {
                            state.Break();
                        }

                        var scriptProcessorTypeKey = scriptProcessorType.HasValue ? scriptProcessorType.Value.ToString() : "";
                        var inst = CreateInstance(ajaxClassItem, webModeType, scriptProcessorType);
                        if (listAuxFunctions.Contains(scriptProcessorTypeKey) == false)
                        {
                            scriptCache[0].Append(inst.ScriptTemplate.GetAuxiliarFunctions());
                            listAuxFunctions.Add(scriptProcessorTypeKey);
                        }
                        if (methodList.IsNullOrWhiteSpaceMtn() == false)
                        {
                            var listMeth = from ajxMeth in localAjaxClass.AjaxScriptMethodCollection
                                           join ajxMReq in methodList.SplitMtn(",").OrderBy(x => x).ToList()
                                           on ajxMeth.Key equals ajxMReq.ToLowerInvariant().Md5Mtn(true)
                                           select ajxMeth.Value;
                            var strScript = new StringBuilder("");


                            if (localAjaxClass.ScriptProcessor != scriptProcessorType || localAjaxClass.UseTraditionalParameterForm != useTraditionalParameterForm)
                            {
                                strScript.Append(inst.CreateClassCode());
                                Parallel.ForEach(listMeth.ToList(), ajaxClassMeth =>
                                {
                                    var classItem = Config.AjaxClassItemCollection.Where(x => x.Key == localAjaxClass.AjaxClassKey).Select(x => x.Value).FirstOrDefault();
                                    if (classItem != null)
                                    {
                                        var meth           = ajaxClassMeth;
                                        var ajaxMethodItem = classItem.AjaxMethodItemCollection
                                                             .Where(x => x.Key == meth.Key).Select((x => x.Value)).FirstOrDefault();

                                        inst.CreateMethodCode(ajaxMethodItem, ref strScript, useTraditionalParameterForm);
                                    }
                                });
                                scriptCache[0].AppendLine((writeMinified) ? Utils.Minifier.MinifyCode(strScript.ToString()) : strScript.ToString());
                            }
                            else
                            {
                                scriptCache[0].AppendLine((writeMinified) ? ajaxClass.ScriptMinified : ajaxClass.Script);
                                Parallel.ForEach(listMeth.ToList(), ajaxClassMeth => scriptCache[0].AppendLine((writeMinified) ? ajaxClassMeth.ScriptMinified : ajaxClassMeth.Script));
                            }
                        }
                        else
                        {
                            if (ajaxClass.ScriptProcessor == scriptProcessorType)
                            {
                                scriptCache[0].AppendLine(writeMinified ? ajaxClass.FullScriptMinified : ajaxClass.FullScript);
                            }
                            else
                            {
                                var scriptFull = inst.CreateFullCode(useTraditionalParameterForm);
                                scriptCache[0].AppendLine(writeMinified ? Utils.Minifier.MinifyCode(scriptFull) : scriptFull);
                            }
                        }
                    });
                }
                else
                {
                    foreach (var ajaxClass in Config.AjaxScriptCollection.Select(x => x.Value))
                    {
                        var ajaxClassItem = Config.AjaxClassItemCollection.Where(x => x.Key == ajaxClass.AjaxClassKey).Select(
                            x => x.Value).FirstOrDefault();
                        if (ajaxClassItem == null)
                        {
                            continue;
                        }
                        var scriptProcessorTypeKey = scriptProcessorType.HasValue?scriptProcessorType.Value.ToString():"";
                        var inst = CreateInstance(ajaxClassItem, webModeType, scriptProcessorType);
                        if (listAuxFunctions.Contains(scriptProcessorTypeKey) == false)
                        {
                            scriptCache[0].Append(inst.ScriptTemplate.GetAuxiliarFunctions());
                            listAuxFunctions.Add(scriptProcessorTypeKey);
                        }
                        if (ajaxClass.ScriptProcessor == scriptProcessorType)
                        {
                            scriptCache[0].AppendLine(writeMinified ? ajaxClass.FullScriptMinified : ajaxClass.FullScript);
                        }
                        else
                        {
                            var scriptFull = inst.CreateFullCode(useTraditionalParameterForm);
                            scriptCache[0].AppendLine(writeMinified ? Utils.Minifier.MinifyCode(scriptFull) : scriptFull);
                        }
                    }
                }

                if (routeName.IsNullOrWhiteSpaceMtn())
                {
                    scriptCache[0] = scriptCache[0].Replace("{MtnMvcRoute}", webModeType == WebModeType.AjaxHandler ? "mtnajax." + Utils.Parameter.AjaxExtension + "/" : "");
                }
                else
                {
                    scriptCache[0] = scriptCache[0].Replace("{MtnMvcRoute}", routeName.ToLowerInvariant() + "/");
                }

                Cache.Instance.Add(MtnAjaxCacheType.AjaxScriptMethod, scriptCache[0].ToString(), hashtag);
            }
            else if (writeOnBody)
            {
                scriptCache[0].Append(Cache.Instance[MtnAjaxCacheType.AjaxScriptMethod, hashtag]);
            }

            if (exportFile && Directory.Exists(HttpContext.Current.Server.MapPath(virtualPath)))
            {
                string extension = ((Utils.Parameter.UseAjaxExtension && webModeType == WebModeType.MvcController) ? "" : "." + Utils.Parameter.AjaxExtension);
                var    filename  = HttpContext.Current.Server.MapPath(virtualPath) + "\\mtn." + hashtag + (writeMinified ? ".min" : "") + extension;
                scriptCache[0].ToString().ToFileMtn(filePath: filename);
            }

            var hostUrl = HttpContext.Current.Request.Url.AbsoluteUri;

            hostUrl = hostUrl.Substring(0, hostUrl.LastIndexOf(HttpContext.Current.Request.Url.AbsolutePath)) + HttpContext.Current.Request.ApplicationPath;
            if (writeOnBody)
            {
                scriptCache[0].Insert(0, ScriptProcessorEngine.GetStartScriptCode(Utils.Parameter.DisableMtnScriptForClasses));
                script.AppendFormat("<script type=\"text/javascript\">\n{0}</script>", scriptCache[0]);
            }
            else
            {
                string extension = ((!Utils.Parameter.UseAjaxExtension && webModeType == WebModeType.MvcController) ? "/" : "." + Utils.Parameter.AjaxExtension);
                script.AppendFormat(
                    "<script language=\"Javascript\" type=\"text/javascript\" src=\"{0}/{1}mtnajaxmethods{2}?hashtag={3}\" {4} {5}></script>",
                    (hostUrl.EndsWith("/")?hostUrl.Substring(0, hostUrl.Length - 1):hostUrl), routeName.IsNullOrWhiteSpaceMtn() ? "" : (routeName + "/"), extension, hashtag, isDeferScript ? "defer" : "", isAsync ? "async" : "");
            }

            return(script.ToString());
        }