/// <summary>
        /// Renders a node graph system
        /// </summary>
        /// <param name="objectExportSnippet">Object export snippet</param>
        /// <param name="flexFieldObject">Flex field object</param>
        /// <returns>Node graph render result</returns>
        private ExportNodeGraphRenderResult RenderNodeGraph(ObjectExportSnippet objectExportSnippet, FlexFieldObject flexFieldObject)
        {
            if (objectExportSnippet == null || objectExportSnippet.ScriptNodeGraph == null)
            {
                return(new ExportNodeGraphRenderResult());
            }

            if (_renderedNodeGraphs.ContainsKey(objectExportSnippet.Id))
            {
                return(_renderedNodeGraphs[objectExportSnippet.Id]);
            }

            ExportNodeGraphRenderResult renderResult;

            try
            {
                _errorCollection.CurrentErrorContext = _localizer["ExportSnippetErrorContext", objectExportSnippet.SnippetName].Value;
                _nodeGraphExporter.SetErrorCollection(_errorCollection);
                _nodeGraphExporter.SetNodeGraphFunctionGenerator(_exportSnippetNodeGraphGenerator);
                _nodeGraphExporter.SetNodeGraphRenderer(_nodeGraphRenderer);
                renderResult = _nodeGraphExporter.RenderNodeGraph(objectExportSnippet.ScriptNodeGraph, flexFieldObject).Result;
                _renderedNodeGraphs.Add(objectExportSnippet.Id, renderResult);
            }
            finally
            {
                _errorCollection.CurrentErrorContext = string.Empty;
            }
            return(renderResult);
        }
        /// <summary>
        /// Renders a code function
        /// </summary>
        /// <param name="exportSnippet">Export snippet to render the code for</param>
        /// <returns>Export snippet function</returns>
        private List <ExportSnippetFunction> RenderCodeFunction(ObjectExportSnippet exportSnippet)
        {
            ExportSnippetFunction function = new ExportSnippetFunction();

            function.FunctionName      = exportSnippet.SnippetName;
            function.Code              = exportSnippet.ScriptCode;
            function.ParentPreviewText = "";

            return(new List <ExportSnippetFunction> {
                function
            });
        }
        /// <summary>
        /// Exports the code snippet additional functions
        /// </summary>
        /// <param name="objectExportSnippet">Object export snippet to export</param>
        /// <param name="flexFieldObject">Flex field object</param>
        /// <param name="listIndent">Indent of the code</param>
        /// <returns>Result of the snippet render</returns>
        private string ExportCodeSnippetAdditionalFunctions(ObjectExportSnippet objectExportSnippet, FlexFieldObject flexFieldObject, string listIndent)
        {
            if (objectExportSnippet == null)
            {
                return(string.Empty);
            }

            if (objectExportSnippet.ScriptType == ExportConstants.ScriptType_NodeGraph)
            {
                return(ExportUtil.IndentListTemplate(this.RenderNodeGraph(objectExportSnippet, flexFieldObject).AdditionalFunctionsCode, listIndent));
            }

            return(string.Empty);
        }
        /// <summary>
        /// Returns true if an object export snippet has additional functions
        /// </summary>
        /// <param name="objectExportSnippet">Object export snippet to export</param>
        /// <param name="flexFieldObject">Flex field object</param>
        /// <returns>true if the snippet has additioanl functions</returns>
        private bool HasCodeSnippetAdditionalFunctions(ObjectExportSnippet objectExportSnippet, FlexFieldObject flexFieldObject)
        {
            if (objectExportSnippet == null)
            {
                return(false);
            }

            if (objectExportSnippet.ScriptType == ExportConstants.ScriptType_NodeGraph)
            {
                return(!string.IsNullOrWhiteSpace(this.RenderNodeGraph(objectExportSnippet, flexFieldObject).AdditionalFunctionsCode));
            }

            return(false);
        }
        /// <summary>
        /// Exports the code snippet content
        /// </summary>
        /// <param name="objectExportSnippet">Object export snippet to export</param>
        /// <param name="flexFieldObject">Flex field object</param>
        /// <param name="listIndent">Indent of the code</param>
        /// <returns>Result of the snippet render</returns>
        private string ExportCodeSnippetContent(ObjectExportSnippet objectExportSnippet, FlexFieldObject flexFieldObject, string listIndent)
        {
            if (objectExportSnippet == null)
            {
                return(string.Empty);
            }

            if (objectExportSnippet.ScriptType == ExportConstants.ScriptType_NodeGraph)
            {
                return(ExportUtil.IndentListTemplate(this.RenderNodeGraph(objectExportSnippet, flexFieldObject).StartStepCode, listIndent));
            }
            else if (objectExportSnippet.ScriptType == ExportConstants.ScriptType_Code)
            {
                return(ExportUtil.IndentListTemplate(objectExportSnippet.ScriptCode != null ? objectExportSnippet.ScriptCode : string.Empty, listIndent));
            }

            return(string.Empty);
        }
        /// <summary>
        /// Checks an skill for update
        /// </summary>
        /// <param name="exportSnippet">Export Snippet</param>
        /// <param name="objectId">Object Id</param>
        /// <param name="timelineEvent">Timeline Event</param>
        /// <returns>Result of update</returns>
        private async Task <FlexFieldObject> CheckSkillForUpdate(ObjectExportSnippet exportSnippet, string objectId, TimelineEvent timelineEvent)
        {
            EvneSkill skill = await _skillDbAccess.GetFlexFieldObjectById(objectId);

            if (skill == null)
            {
                return(null);
            }

            await _timelineService.AddTimelineEntry(exportSnippet.ProjectId, timelineEvent, exportSnippet.SnippetName, skill.Name, skill.Id);

            CompareResult result = await _implementationStatusComparer.CompareSkill(skill.Id, skill);

            if (result.CompareDifference != null && result.CompareDifference.Count > 0)
            {
                skill.IsImplemented = false;
                await _skillDbAccess.UpdateFlexFieldObject(skill);
            }

            return(skill);
        }
        /// <summary>
        /// Checks an item for update
        /// </summary>
        /// <param name="exportSnippet">Export Snippet</param>
        /// <param name="objectId">Object Id</param>
        /// <param name="timelineEvent">Timeline Event</param>
        /// <returns>Result of update</returns>
        private async Task <FlexFieldObject> CheckItemForUpdate(ObjectExportSnippet exportSnippet, string objectId, TimelineEvent timelineEvent)
        {
            StyrItem item = await _itemDbAccess.GetFlexFieldObjectById(objectId);

            if (item == null)
            {
                return(null);
            }

            await _timelineService.AddTimelineEntry(exportSnippet.ProjectId, timelineEvent, exportSnippet.SnippetName, item.Name, item.Id);

            CompareResult result = await _implementationStatusComparer.CompareItem(item.Id, item);

            if (result.CompareDifference != null && result.CompareDifference.Count > 0)
            {
                item.IsImplemented = false;
                await _itemDbAccess.UpdateFlexFieldObject(item);
            }

            return(item);
        }
        /// <summary>
        /// Checks an npc for update
        /// </summary>
        /// <param name="exportSnippet">Export Snippet</param>
        /// <param name="objectId">Object Id</param>
        /// <param name="timelineEvent">Timeline Event</param>
        /// <returns>Result of update</returns>
        private async Task <FlexFieldObject> CheckNpcForUpdate(ObjectExportSnippet exportSnippet, string objectId, TimelineEvent timelineEvent)
        {
            KortistoNpc npc = await _npcDbAccess.GetFlexFieldObjectById(objectId);

            if (npc == null)
            {
                return(null);
            }

            await _timelineService.AddTimelineEntry(exportSnippet.ProjectId, timelineEvent, exportSnippet.SnippetName, npc.Name, npc.Id);

            CompareResult result = await _implementationStatusComparer.CompareNpc(npc.Id, npc);

            if (result.CompareDifference != null && result.CompareDifference.Count > 0)
            {
                npc.IsImplemented = false;
                await _npcDbAccess.UpdateFlexFieldObject(npc);
            }

            return(npc);
        }
        /// <summary>
        /// Checks the related object of an export snippet on deletion
        /// </summary>
        /// <param name="exportSnippet">Export Snippet</param>
        /// <param name="objectType">Object Type</param>
        /// <param name="objectId">Object Id</param>
        /// <returns>Result of the deletion check</returns>
        public async Task <FlexFieldObject> CheckExportSnippetRelatedObjectOnDelete(ObjectExportSnippet exportSnippet, string objectType, string objectId)
        {
            if (string.IsNullOrEmpty(objectType))
            {
                return(null);
            }

            objectType = objectType.ToLowerInvariant();
            if (objectType == "npc")
            {
                return(await CheckNpcForUpdate(exportSnippet, objectId, TimelineEvent.KortistoNpcExportSnippetDeleted));
            }
            else if (objectType == "item")
            {
                return(await CheckItemForUpdate(exportSnippet, objectId, TimelineEvent.StyrItemExportSnippetDeleted));
            }
            else if (objectType == "skill")
            {
                return(await CheckSkillForUpdate(exportSnippet, objectId, TimelineEvent.EvneSkillExportSnippetDeleted));
            }

            return(null);
        }
        /// <summary>
        /// Renders a list of export snippet functions
        /// </summary>
        /// <param name="exportSnippet">Export snippet to render</param>
        /// <param name="flexFieldObject">Object to which the snippets belong</param>
        /// <returns>List of export snippet functions</returns>
        public async Task <List <ExportSnippetFunction> > RenderExportSnippetFunctions(ObjectExportSnippet exportSnippet, FlexFieldObject flexFieldObject)
        {
            if (exportSnippet == null || exportSnippet.ScriptType == ExportConstants.ScriptType_None)
            {
                return(new List <ExportSnippetFunction>());
            }

            if (exportSnippet.ScriptType == ExportConstants.ScriptType_Code)
            {
                return(RenderCodeFunction(exportSnippet));
            }
            else if (exportSnippet.ScriptType == ExportConstants.ScriptType_NodeGraph)
            {
                return(await RenderExportSnippetNodeGraph(exportSnippet.SnippetName, exportSnippet.ScriptNodeGraph, flexFieldObject));
            }

            return(new List <ExportSnippetFunction>());
        }
        /// <summary>
        /// Returns true if an object export snippet has additional functions
        /// </summary>
        /// <param name="renderedFunctions">Rendered function cache</param>
        /// <param name="objectExportSnippet">Object export snippet to export</param>
        /// <param name="flexFieldObject">Flex field object</param>
        /// <returns>true if the snippet has additioanl functions</returns>
        private async Task <bool> HasCodeSnippetAdditionalFunctions(Dictionary <string, List <ExportSnippetFunction> > renderedFunctions, ObjectExportSnippet objectExportSnippet, FlexFieldObject flexFieldObject)
        {
            if (objectExportSnippet == null)
            {
                return(false);
            }

            List <ExportSnippetFunction> functions = await RenderFunctions(renderedFunctions, objectExportSnippet, flexFieldObject);

            return(functions.Count > 1);
        }
        /// <summary>
        /// Exports the code snippet additional functions
        /// </summary>
        /// <param name="renderedFunctions">Rendered function cache</param>
        /// <param name="objectExportSnippet">Object export snippet to export</param>
        /// <param name="flexFieldObject">Flex field object</param>
        /// <param name="listIndent">Indent of the code</param>
        /// <returns>Result of the snippet render</returns>
        private async Task <string> ExportCodeSnippetAdditionalFunctions(Dictionary <string, List <ExportSnippetFunction> > renderedFunctions, ObjectExportSnippet objectExportSnippet, FlexFieldObject flexFieldObject, string listIndent)
        {
            if (objectExportSnippet == null)
            {
                return(string.Empty);
            }

            GoNorthProject project = await _cachedDbAccess.GetUserProject();

            ExportTemplate functionContentTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(project.Id, TemplateType.ObjectExportSnippetFunction);

            List <ExportSnippetFunction> functions = await RenderFunctions(renderedFunctions, objectExportSnippet, flexFieldObject);

            List <ExportSnippetFunction> additionalFunctions = functions.Skip(1).ToList();

            string functionList = string.Empty;

            foreach (ExportSnippetFunction curFunction in additionalFunctions)
            {
                functionList += await RenderExportSnippetFunction(functionContentTemplate, curFunction);
            }

            return(ExportUtil.IndentListTemplate(functionList, listIndent));
        }
        /// <summary>
        /// Exports the code snippet content
        /// </summary>
        /// <param name="renderedFunctions">Rendered function cache</param>
        /// <param name="objectExportSnippet">Object export snippet to export</param>
        /// <param name="flexFieldObject">Flex field object</param>
        /// <param name="listIndent">Indent of the code</param>
        /// <returns>Result of the snippet render</returns>
        private async Task <string> ExportCodeSnippetContent(Dictionary <string, List <ExportSnippetFunction> > renderedFunctions, ObjectExportSnippet objectExportSnippet, FlexFieldObject flexFieldObject, string listIndent)
        {
            if (objectExportSnippet == null)
            {
                return(string.Empty);
            }

            List <ExportSnippetFunction> functions = await RenderFunctions(renderedFunctions, objectExportSnippet, flexFieldObject);

            if (!functions.Any())
            {
                return(string.Empty);
            }

            return(ExportUtil.IndentListTemplate(functions.First().Code, listIndent));
        }
        /// <summary>
        /// Renders the function for an export snippet
        /// </summary>
        /// <param name="renderedFunctions">Rendered function cache</param>
        /// <param name="objectExportSnippet">Export snippet to render</param>
        /// <param name="flexFieldObject">Flex field object to which the snippets belong</param>
        /// <returns>Rendered function</returns>
        private async Task <List <ExportSnippetFunction> > RenderFunctions(Dictionary <string, List <ExportSnippetFunction> > renderedFunctions, ObjectExportSnippet objectExportSnippet, FlexFieldObject flexFieldObject)
        {
            if (renderedFunctions.ContainsKey(objectExportSnippet.SnippetName))
            {
                return(renderedFunctions[objectExportSnippet.SnippetName]);
            }

            _snippetFunctionRenderer.SetErrorCollection(_errorCollection);

            List <ExportSnippetFunction> functions = await _snippetFunctionRenderer.RenderExportSnippetFunctions(objectExportSnippet, flexFieldObject);

            renderedFunctions.Add(objectExportSnippet.SnippetName, functions);

            return(functions);
        }