public DateTime NextScheduledAtUtc(DateTime lastScheduledAtUtc, ScheduledMessageRecurrenceEnum recurrenceType)
        {
            if (recurrenceType == ScheduledMessageRecurrenceEnum.DoesNotRecur)
            {
                throw new NotSupportedException("Only daily recurrence is currently supported");
            }

            if (Calculators.TryGetValue(recurrenceType, out var adjustmentFunc))
            {
                return(adjustmentFunc(lastScheduledAtUtc));
            }

            throw new NotSupportedException($"Recurrence type {recurrenceType} has no registered calculator");
        }
        public async Task <string> ScheduleCommand(ScheduledMessageRecurrenceEnum frequency, ICommand <bool> command, DateTime?initialExecutionDateTimeUtc, string optionalMessageId = null)
        {
            if (command == null)
            {
                throw new ArgumentNullException(nameof(command));
            }
            if (initialExecutionDateTimeUtc.HasValue && initialExecutionDateTimeUtc < DateTime.UtcNow)
            {
                throw new ArgumentException("Commands cannot be scheduled to run in the past");
            }

            if (frequency == ScheduledMessageRecurrenceEnum.DoesNotRecur && !initialExecutionDateTimeUtc.HasValue)
            {
                throw new ArgumentException("A one off command must have an execution date", nameof(initialExecutionDateTimeUtc));
            }

            ScheduledMessage message = CreateScheduledMessage(command, initialExecutionDateTimeUtc, optionalMessageId, frequency);

            await PostMessage(initialExecutionDateTimeUtc, message);

            return(message.Id);
        }
        private static ScheduledMessage CreateScheduledMessage(ICommand <bool> command,
                                                               DateTime?initialExecutionDateTimeUtc,
                                                               string optionalMessageId, ScheduledMessageRecurrenceEnum frequency)
        {
            DateTime scheduledAt        = initialExecutionDateTimeUtc ?? DateTime.UtcNow;
            string   messageId          = string.IsNullOrWhiteSpace(optionalMessageId) ? Guid.NewGuid().ToString() : optionalMessageId;
            string   wrappedCommandJson = JsonConvert.SerializeObject(command);

            return(new ScheduledMessage
            {
                Id = messageId,
                LastScheduledAtUtc = null,
                LastExecutedAtUtc = null,
                Recurrence = frequency,
                ScheduledAtUtc = scheduledAt,
                WrappedCommandFullTypeName = command.GetType().FullName,
                WrappedCommandJson = wrappedCommandJson
            });
        }