/// <summary>
        /// Gets the content of aggregate keys
        /// </summary>
        /// <param name="script"></param>
        /// <param name="keyBuffName"></param>
        /// <returns></returns>
        private string GetAggregateKeyExtraction(DonutScript script, string keyBuffName)
        {
            var rootIgn = script.GetRootIntegration();
            var ignKeys = rootIgn.AggregateKeys;

            if (ignKeys == null || !ignKeys.Any())
            {
                throw new Exception("Integration has no aggregate keys!");
            }
            var keys = ignKeys.Where(x => x.Operation != null);
//            if (keys == null || !keys.Any())
//            {
//                throw new Exception("Integration has no evaluable aggregate keys!");
//            }
            var buffer = new StringBuilder();
            int iKey   = 0;

            buffer.AppendLine($"var {keyBuffName} = new Dictionary<string, object>();");
            foreach (var key in keys)
            {
                var keyName    = $"aggKey{iKey}";
                var evalFnName = $"{keyName}_fn";
                var evalFn     = key.Operation.GetCallCode(evalFnName).ToString();
                //var keyVar = $"var {keyName} = {evalFnName}(document[\"{key.Arguments}\"]);";
                var keyLine = $"{keyBuffName}[\"{key.Name}\"] = {evalFnName}(document[\"{key.Arguments}\"]);";
                buffer.AppendLine(evalFn);
                buffer.AppendLine(keyLine);
                iKey++;
            }

            buffer.AppendLine($"var groupKey = Context.AddMetaGroup({keyBuffName});");
            return(buffer.ToString());
        }
        /// <summary>
        /// Generates a donutfile
        /// </summary>
        /// <param name="namespace"></param>
        /// <param name="script"></param>
        /// <returns></returns>
        public string GenerateDonut(string @namespace, DonutScript script)
        {
            string donutTemplate;
            var    baseName     = script.Type.GetClassName();
            var    conutextName = script.Type.GetContextName();

            _expVisitor.Clear();
            _expVisitor.SetScript(script);
            var encoding = System.Text.Encoding.UTF8;

            using (StreamReader reader = new StreamReader(GetTemplate("Donutfile.txt"), encoding))
            {
                donutTemplate = reader.ReadToEnd();
                if (string.IsNullOrEmpty(donutTemplate))
                {
                    throw new Exception("Template empty!");
                }
                var donutComment = $"//Generated on {DateTime.UtcNow} UTC\n";
                donutComment += $"//Root collection on {script.GetRootIntegration().Collection}\n";
                donutTemplate = $"{donutComment}\n" + donutTemplate;
                donutTemplate = donutTemplate.Replace("$Namespace", @namespace);
                donutTemplate = donutTemplate.Replace("$ClassName", baseName);
                donutTemplate = donutTemplate.Replace("$ContextTypeName", conutextName);
                var prepareScript = GeneratePrepareExtractionContent(script);
                donutTemplate = donutTemplate.Replace("$PrepareExtraction", prepareScript);
                donutTemplate = ProcessFeaturePrepContent(donutTemplate, script); //donutTemplate.Replace("$ExtractionBody", GetFeaturePrepContent(donutTemplate, script));
                donutTemplate = donutTemplate.Replace("$CompleteExtraction", GetFeatureExtractionCompletion(script));
                var propertiesContent = GenerateDonutPropertiesContent(!string.IsNullOrEmpty(prepareScript));
                donutTemplate  = donutTemplate.Replace("$DonutProperties", propertiesContent);
                donutTemplate  = donutTemplate.Replace("$OnFinished", GenerateOnDounutFinishedContent(script));
                donutTemplate += "\n\n" +
                                 "/* Donut script: \n" + script.ToString() +
                                 "\n*/";
                //Items: $ClassName, $ContextTypeName, $ExtractionBody, $OnFinished
            }
            return(donutTemplate);
        }