// Remove a control from a course. Caller must ensure the current is actually in this course.
// Returns a list of all control points that were deleted. This will include the one asked to remove,
// but might also remove others if it starts a fork or loop.
public static ICollection<Id<ControlPoint>> RemoveCourseControl(EventDB eventDB, Id<Course> courseId, Id<CourseControl> courseControlIdRemove)
{
Course course = eventDB.GetCourse(courseId);
List<Id<CourseControl>> allCourseControls = QueryEvent.EnumCourseControlIds(eventDB, new CourseDesignator(courseId)).ToList();
// This the course control to change to. Could be None.
CourseControl courseControlRemove = eventDB.GetCourseControl(courseControlIdRemove);
Id<CourseControl> afterRemove = courseControlRemove.nextCourseControl;
if (courseControlRemove.split && !courseControlRemove.loop) {
// Change next to another one of the split controls.
if (courseControlRemove.splitCourseControls[0] == courseControlIdRemove)
afterRemove = courseControlRemove.splitCourseControls[1];
else
afterRemove = courseControlRemove.splitCourseControls[0];
}
// For each course control, go throught and change referecnes to the subsequent control.
foreach (Id<CourseControl> courseControlId in allCourseControls) {
bool changed = false;
CourseControl courseControl = eventDB.GetCourseControl(courseControlId);
CourseControl clone = (CourseControl)courseControl.Clone();
if (courseControl.nextCourseControl == courseControlIdRemove) {
changed = true;
clone.nextCourseControl = afterRemove;
}
if (courseControl.split && courseControl.splitEnd == courseControlIdRemove) {
changed = true;
clone.splitEnd = afterRemove;
if (afterRemove.IsNone) {
clone.split = false; // No join control means we remove the split entirely.
clone.splitCourseControls = null;
}
}
if (clone.split && clone.splitCourseControls.Contains(courseControlIdRemove)) {
changed = true;
clone.splitCourseControls = clone.splitCourseControls.Where(id => id != courseControlIdRemove).ToArray();
if (clone.splitCourseControls.Length < 2) {
clone.split = false;
clone.loop = false;
clone.splitCourseControls = null;
clone.splitEnd = Id<CourseControl>.None;
}
}
if (changed) {
eventDB.ReplaceCourseControl(courseControlId, clone);
}
}
if (course.firstCourseControl == courseControlIdRemove) {
// Special case -- remove the first course control.
course = (Course) course.Clone();
course.firstCourseControl = afterRemove;
eventDB.ReplaceCourse(courseId, course);
}
// Remove a split could orphan more than one control. Go through and find orphaned ones.
HashSet<Id<CourseControl>> newCourseControls = new HashSet<Id<CourseControl>>(QueryEvent.EnumCourseControlIds(eventDB, new CourseDesignator(courseId)));
List<Id<CourseControl>> removedCourseControls = new List<Id<CourseControl>>();
HashSet<Id<ControlPoint>> removedControls = new HashSet<Id<ControlPoint>>();
foreach (Id<CourseControl> courseControlId in allCourseControls) {
if (!newCourseControls.Contains(courseControlId)) {
removedControls.Add(eventDB.GetCourseControl(courseControlId).control);
removedCourseControls.Add(courseControlId);
eventDB.RemoveCourseControl(courseControlId);
}
}
if (! removedCourseControls.Contains(courseControlIdRemove)) {
Debug.Fail("Did not remove the course control we were removing.");
}
return removedControls;
}