Example #1
0
        /// <summary>
        /// RPC-method for adding a course to the schedule and for
        /// adding the calling user to a course that someone else
        /// has already added.
        /// </summary>
        /// <param name="courseId">Course ID</param>
        /// <returns></returns>
        public async Task AddCourse(string courseId)
        {
            using (var errorReporter = new ErrorReporter(s => CallingClient.Errors.ScheduleMessage = s))
            {
                var course = PaulRepository.Courses.FirstOrDefault(c => c.Id == courseId);

                if (course == null)
                {
                    errorReporter.Throw(
                        new ArgumentException("Course not found", nameof(courseId)),
                        UserErrorsViewModel.GenericErrorMessage);
                }


                var schedule = CallingClient.SharedScheduleVM.Schedule;

                await CallingClient.SharedScheduleVM.TimetableHubSemaphore.WaitAsync();

                try
                {
                    var selectedCourse = schedule.SelectedCourses.FirstOrDefault(c => c.CourseId == courseId);

                    if (course.IsTutorial)
                    {
                        // The user has decided to select a pending tutorial or one
                        // that was already selected by another user, so remove all pending
                        // tutorials of this course
                        CallingClient.TailoredScheduleVM.RemovePendingTutorials(course, errorReporter);

                        // Remove user from other possibly selected tutorial
                        var parentCourse          = schedule.SelectedCourses.First(sel => sel.Course.AllTutorials.SelectMany(it => it).Contains(course));
                        var otherSelectedTutorial = parentCourse.Course.AllTutorials
                                                    .FirstOrDefault(group => group.Contains(course))
                                                    ?.FirstOrDefault(tut => schedule.SelectedCourses.Any(sel => Equals(tut, sel.Course) && sel.Users.Select(it => it.User).Contains(CallingClient.User)));
                        if (otherSelectedTutorial != null)
                        {
                            await RemoveUserFromCourse(otherSelectedTutorial.Id, acquireSemaphore : false);
                        }


                        //If the user hasn't selected the parent course of the tutorial, it will be added here
                        if (parentCourse.Users.All(u => u.User.Name != CallingClient.Name))
                        {
                            var connectedCourses = parentCourse.Course.ConnectedCourses.Concat(new[] { parentCourse.Course });
                            foreach (var c in connectedCourses)
                            {
                                await PaulRepository.AddUserToSelectedCourseAsync(schedule.SelectedCourses.First(s => s.CourseId == c.Id), CallingClient.User);
                            }
                        }
                    }

                    if (selectedCourse == null)
                    {
                        var connectedCourses = course.ConnectedCourses.Concat(new[] { course })
                                               .Select(it => PaulRepository.CreateSelectedCourse(schedule, CallingClient.User, it))
                                               .ToList();

                        await PaulRepository.AddCourseToScheduleAsync(schedule, connectedCourses);

                        AddTutorialsForCourse(courseId);
                    }
                    else if (selectedCourse.Users.All(u => u.User != CallingClient.User))
                    {
                        // The course has already been added to the schedule by someone else.
                        // Add the calling user to the selected course (if not yet done).

                        await PaulRepository.AddUserToSelectedCourseAsync(selectedCourse, CallingClient.User);

                        var connectedCourseIds = selectedCourse.Course.ConnectedCourses.Select(it => it.Id).ToList();

                        var selectedConnectedCourses = schedule.SelectedCourses
                                                       .Where(selCo => connectedCourseIds.Contains(selCo.CourseId));

                        foreach (var connectedCourse in selectedConnectedCourses)
                        {
                            await PaulRepository.AddUserToSelectedCourseAsync(connectedCourse, CallingClient.User);
                        }
                    }

                    UpdateAddedStateInSearchResultsAndCourseList(course, isAdded: true);
                }
                finally
                {
                    CallingClient.SharedScheduleVM.TimetableHubSemaphore.Release();
                }
                UpdateTailoredViewModels();
            }
        }