Example #1
0
        public ActionResult <Group> CreateOrUpdateGroup([FromBody] Group.Input.CreateGroupBody body, [FromQuery] bool merge = false)
        {
            // Validate if the parent exists if a parent id is set.
            var parentID = body.ParentID ?? 0;

            if (parentID != 0)
            {
                var parent = RepoFactory.AnimeGroup.GetByID(parentID);
                if (parent == null)
                {
                    return(BadRequest("Invalid parent group id supplied."));
                }
            }

            // Try to find the group to merge with if we provided an id.
            bool           isNew = false;
            SVR_AnimeGroup group = null;

            if (body.ID.HasValue && body.ID.Value != 0)
            {
                // Make sure merging is requested.
                // A merge request without the 'merge' query parameter set is an
                // error.
                if (!merge)
                {
                    return(BadRequest("A group id have been supplied. Set the merge query parameter to continue."));
                }

                group = RepoFactory.AnimeGroup.GetByID(body.ID.Value);

                // Make sure the group actually exists.
                if (group == null)
                {
                    return(BadRequest("No Group entry for the given id."));
                }
            }
            // Try to find an existing group exists for the given name or create a new one.
            else
            {
                // Look for an existing group if force is not set.
                group = RepoFactory.AnimeGroup.GetByParentID(parentID)
                        .FirstOrDefault(grp => string.Equals(grp.GroupName, body.Name, StringComparison.InvariantCultureIgnoreCase));

                // If no group was found (either because we forced it or because a group by the same name was not found) then
                if (group == null)
                {
                    // It's safe to use the group name.
                    isNew = true;
                    group = new()
                    {
                        Description               = string.Empty,
                        IsManuallyNamed           = 0,
                        DateTimeCreated           = DateTime.Now,
                        DateTimeUpdated           = DateTime.Now,
                        MissingEpisodeCount       = 0,
                        MissingEpisodeCountGroups = 0,
                        OverrideDescription       = 0,
                    };
                }
                // Else we need to provide the query parameter to either merge
                // or forcefully create a new group.
                else if (!merge)
                {
                    return(BadRequest("A group with the given name already exists. Set the merge or force query parameter to continue."));
                }
            }

            // Get the series and validate the series ids.
            var seriesList = body.SeriesIDs?.Select(id => RepoFactory.AnimeSeries.GetByID(id)).Where(s => s != null).ToList() ?? new();

            if (seriesList.Count != (body.SeriesIDs?.Length ?? 0))
            {
                return(BadRequest("One or more series ids are invalid."));
            }
            // Trying to merge 0 series with an existing group is an error.
            // Trying to create an empty group is also an error.
            if (seriesList.Count == 0)
            {
                return(BadRequest("No series ids have been spesified."));
            }

            // Nor spesifying a group name is an error.
            body.Name = body.Name?.Trim() ?? "";
            if (string.IsNullOrEmpty(body.Name))
            {
                return(BadRequest("A name must be present and contain at least one character."));
            }

            group.AnimeGroupParentID  = parentID != 0 ? parentID : null;
            group.GroupName           = body.Name;
            group.SortName            = string.IsNullOrEmpty(body.SortName?.Trim()) ? body.Name : body.SortName;
            group.Description         = body.Description ?? null;
            group.IsManuallyNamed     = body.HasCustomName ? 1 : 0;
            group.OverrideDescription = 0;

            // Create a new or update an existing group entry.
            RepoFactory.AnimeGroup.Save(group, true, false, false);

            // Iterate over the series list to calculate the groups to update
            // and to assign the series to the group.
            var oldGroups = new Dictionary <int, int>();

            foreach (var series in seriesList)
            {
                // Skip the series if it's already in the group.
                if (series.AnimeGroupID == group.AnimeGroupID)
                {
                    continue;
                }

                // Count the number of series in each group.
                var oldGroupID = series.AnimeGroupID;
                if (oldGroups.TryGetValue(oldGroupID, out var count))
                {
                    oldGroups[oldGroupID] = count + 1;
                }
                else
                {
                    oldGroups[oldGroupID] = 1;
                }

                // Assign the series to the new group and update the series
                // entry.
                series.AnimeGroupID = group.AnimeGroupID;
                series.UpdateStats(true, true, false);
            }

            // We don't need to update the group twice, and we don't need to
            // check if the group we're creating/updating needs to be
            // removed.
            if (oldGroups.Keys.Contains(group.AnimeGroupID))
            {
                oldGroups.Remove(group.AnimeGroupID);
            }

            // Remove or update groups stats for the old groups.
            foreach (var(oldGroupID, seriesCount) in oldGroups)
            {
                var oldGroup = RepoFactory.AnimeGroup.GetByID(oldGroupID)?.TopLevelAnimeGroup;
                // The old group may have already been removed, so silently skip it.
                if (oldGroup == null)
                {
                    continue;
                }
                // Delete the sub-groups if the old group doesn't contain any other series.
                if (oldGroup.GetAllSeries().Count <= seriesCount)
                {
                    RepoFactory.AnimeGroup.Delete(oldGroup.GetAllChildGroups());
                    RepoFactory.AnimeGroup.Delete(oldGroup);
                }
                else
                {
                    oldGroup.UpdateStatsFromTopLevel(false, true, true);
                }
            }

            // Update the group stats for the new group.
            group.UpdateStatsFromTopLevel(false, true, true);

            // Return the info for the newly created or updated group.
            var dto = new Group(HttpContext, group);

            return(isNew ? Created($"./{group.AnimeGroupID}", dto) : Ok(dto));
        }