using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using PlotLine.Models; using PlotLine.Services; using PlotLine.ViewModels; namespace PlotLine.Controllers; [Authorize] [Route("Writing")] public sealed class WritingController( IStoryContextService storyContext, IRelationshipMapService relationshipMap, IFloorPlanService floorPlans) : Controller { [HttpGet("Context")] public async Task Context(int? projectId, int? bookId, int? chapterId, int? sceneId) { var model = new WritingContextPageViewModel { ProjectID = projectId, BookID = bookId, ChapterID = chapterId, SceneID = sceneId, Display = sceneId.HasValue ? await BuildDisplayAsync(projectId, bookId, chapterId, sceneId, "Manual context") : new WritingContextDisplayViewModel { FollowStatus = "Connected, waiting for scene" } }; return View(model); } [HttpGet("Context/Scene")] public async Task ContextScene(int? projectId, int? bookId, int? chapterId, int? sceneId) { if (!sceneId.HasValue) { return PartialView("~/Views/Writing/_WritingContextContent.cshtml", new WritingContextDisplayViewModel { FollowStatus = "Connected, waiting for scene" }); } var model = await BuildDisplayAsync(projectId, bookId, chapterId, sceneId, "Following Word"); return model?.HasScene == true ? PartialView("~/Views/Writing/_WritingContextContent.cshtml", model) : NotFound(); } private async Task BuildDisplayAsync(int? projectId, int? bookId, int? chapterId, int? sceneId, string followStatus) { if (!sceneId.HasValue) { return new WritingContextDisplayViewModel { FollowStatus = followStatus }; } var context = await storyContext.GetForSceneAsync(sceneId.Value, projectId, bookId); if (context?.Scene is null) { return null; } var position = context.Position; var relationships = await relationshipMap.GetAsync(position, null, true); var floorPlan = context.Scene.FloorPlanID.HasValue ? await floorPlans.GetEditorAsync(context.Scene.FloorPlanID.Value) : null; return new WritingContextDisplayViewModel { Context = context, RelationshipMap = relationships, FloorPlan = floorPlan, FollowStatus = followStatus, SceneOptions = BuildSceneOptions(context.Scene) }; } private static IReadOnlyList BuildSceneOptions(SceneEditViewModel scene) { var options = scene.SceneOptions .Select(x => new SelectListItem(x.Text, x.Value, x.Value == scene.SceneID.ToString())) .ToList(); if (!options.Any(x => x.Value == scene.SceneID.ToString())) { options.Insert(0, new SelectListItem( $"{scene.Book?.BookDisplayTitle ?? "Book"} / Ch {scene.Chapter?.ChapterNumber:g} / Scene {scene.SceneNumber:g}: {scene.SceneTitle}", scene.SceneID.ToString(), true)); } return options .OrderByDescending(x => x.Selected) .ThenBy(x => x.Text) .ToList(); } }