private static Task OutputSceneFiles(Dictionary <string, CodeCompileUnit> scenes, CodeDomProvider csharp, string directoryFullName)
        {
            var prependScene = CodeGeneration_Scene.SceneClassName("Global Prepend");
            var appendScene  = CodeGeneration_Scene.SceneClassName("Global Append");
            var prepend      = scenes.Any(kvp => kvp.Key.Equals(prependScene, System.StringComparison.OrdinalIgnoreCase));
            var append       = scenes.Any(kvp => kvp.Key.Equals(appendScene, System.StringComparison.OrdinalIgnoreCase));

            return(Task.WhenAll(scenes.Select(async c =>
            {
                var type = c.Value.FirstType();
                if (!type.Name.Equals(prependScene, StringComparison.OrdinalIgnoreCase) &&
                    !type.Name.Equals(appendScene, StringComparison.OrdinalIgnoreCase))
                {
                    var interaction = c.Value.FirstType().MethodStatements(CodeConstants.SceneInteractionMethod);
                    if (interaction?.OfType <CodeSnippetStatement>().Any() ?? false)
                    {
                        var mainCall = interaction.OfType <CodeSnippetStatement>()
                                       .First(ss => ss.Value.EndsWith(CodeConstants.ScenePrimaryMethod.ToLower() + "\":"));
                        var mainInteract = interaction[interaction.IndexOf(mainCall) + 2];


                        if (prepend)
                        {
                            interaction.Insert(interaction.IndexOf(mainInteract),
                                               new CodeExpressionStatement(CodeGeneration_Navigation.GoToScene("global prepend")));
                        }

                        if (append)
                        {
                            interaction.Insert(interaction.IndexOf(mainInteract) + 1,
                                               new CodeExpressionStatement(CodeGeneration_Navigation.GoToScene("global append")));
                        }
                    }
                }

                using (var textWriter =
                           new StreamWriter(File.Open(Path.Combine(directoryFullName, c.Key.Safe()) + ".cs", FileMode.Create, FileAccess.Write)))
                {
                    csharp.GenerateCodeFromCompileUnit(
                        c.Value,
                        textWriter,
                        new System.CodeDom.Compiler.CodeGeneratorOptions());
                    await textWriter.FlushAsync();
                }
            })));
        }
        protected override Task Begin(Scene scene, CodeGeneratorContext context)
        {
            var code       = CodeGeneration_Scene.Generate(scene, context);
            var sceneClass = code.FirstType();

            context.SceneFiles.Add(CodeGeneration_Scene.SceneClassName(scene.Name), code);
            context.CodeScope.Push(sceneClass);
            context.CodeScope.Push(sceneClass.GetMainMethod());

            CodeGeneration_Navigation.RegisterScene(context, scene.Name,
                                                    new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(sceneClass.Name), CodeConstants.SceneInteractionMethod));

            if (scene.Name.Equals(SpecialScenes.Start, StringComparison.OrdinalIgnoreCase))
            {
                context.CreateLaunchRequestHandler();
            }

            return(base.Begin(scene, context));
        }
 public static CodeSnippetStatement AddInteraction(this CodeStatementCollection statements, string sceneName, string interactionName,
                                                   CodeMethodInvokeExpression method, bool whenCandidate = false)
 {
     if (whenCandidate)
     {
         var snippet = new CodeSnippetStatement(
             $"\t\t\tcase \"{interactionName}\" when Navigation.IsCandidate(request,\"{interactionName}\"):");
         statements.AddBeforeReturn(snippet,
                                    method,
                                    new CodeSnippetExpression("\t\t\tbreak")
                                    );
         return(snippet);
     }
     else
     {
         var snippet = new CodeSnippetStatement($"\t\t\tcase \"{interactionName}\":");
         statements.AddBeforeReturn(
             snippet,
             CodeGeneration_Navigation.NotTrackedSceneNames.SelectMany(s => new[] { s, CodeGeneration_Scene.SceneClassName(s) }).Contains(sceneName) ? null : new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Navigation"), "ClearCandidates",
                                                                                                                                                                                             CodeConstants.RequestVariableRef),
             method,
             new CodeSnippetExpression("\t\t\tbreak")
             );
         return(snippet);
     }
 }