protected static async Task <Either <BaseError, ProgramSchedule> > FillerConfigurationMustBeValid(
        TvContext dbContext,
        IProgramScheduleItemRequest item,
        ProgramSchedule programSchedule)
    {
        var allFillerIds = Optional(item.PreRollFillerId)
                           .Append(Optional(item.MidRollFillerId))
                           .Append(Optional(item.PostRollFillerId))
                           .ToList();

        List <FillerPreset> allFiller = await dbContext.FillerPresets
                                        .Filter(fp => allFillerIds.Contains(fp.Id))
                                        .ToListAsync();

        if (allFiller.Count(f => f.PadToNearestMinute.HasValue) > 1)
        {
            return(BaseError.New("Schedule may only contain one filler preset that is configured to pad"));
        }

        if (allFiller.Any(fp => fp.PadToNearestMinute.HasValue) && !item.FallbackFillerId.HasValue)
        {
            return(BaseError.New("Fallback filler is required when padding"));
        }

        return(programSchedule);
    }
    protected Validation <BaseError, ProgramSchedule> CollectionTypeMustBeValid(
        IProgramScheduleItemRequest item,
        ProgramSchedule programSchedule)
    {
        switch (item.CollectionType)
        {
        case ProgramScheduleItemCollectionType.Collection:
            if (item.CollectionId is null)
            {
                return(BaseError.New("[Collection] is required for collection type 'Collection'"));
            }

            break;

        case ProgramScheduleItemCollectionType.TelevisionShow:
            if (item.MediaItemId is null)
            {
                return(BaseError.New("[MediaItem] is required for collection type 'TelevisionShow'"));
            }

            break;

        case ProgramScheduleItemCollectionType.TelevisionSeason:
            if (item.MediaItemId is null)
            {
                return(BaseError.New("[MediaItem] is required for collection type 'TelevisionSeason'"));
            }

            break;

        case ProgramScheduleItemCollectionType.Artist:
            if (item.MediaItemId is null)
            {
                return(BaseError.New("[MediaItem] is required for collection type 'Artist'"));
            }

            break;

        case ProgramScheduleItemCollectionType.MultiCollection:
            if (item.MultiCollectionId is null)
            {
                return(BaseError.New("[MultiCollection] is required for collection type 'MultiCollection'"));
            }

            break;

        case ProgramScheduleItemCollectionType.SmartCollection:
            if (item.SmartCollectionId is null)
            {
                return(BaseError.New("[SmartCollection] is required for collection type 'SmartCollection'"));
            }

            break;

        default:
            return(BaseError.New("[CollectionType] is invalid"));
        }

        return(programSchedule);
    }
    protected static Validation <BaseError, ProgramSchedule> PlayoutModeMustBeValid(
        IProgramScheduleItemRequest item,
        ProgramSchedule programSchedule)
    {
        if (item.MultiCollectionId.HasValue)
        {
            switch (item.PlaybackOrder)
            {
            case PlaybackOrder.Chronological:
            case PlaybackOrder.Random:
                return(BaseError.New($"Invalid playback order for multi collection: '{item.PlaybackOrder}'"));

            case PlaybackOrder.Shuffle:
            case PlaybackOrder.ShuffleInOrder:
                break;
            }
        }

        switch (item.PlayoutMode)
        {
        case PlayoutMode.Flood:
        case PlayoutMode.One:
            break;

        case PlayoutMode.Multiple:
            if (item.MultipleCount.GetValueOrDefault() < 0)
            {
                return(BaseError.New(
                           "[MultipleCount] must be greater than or equal to 0 for playout mode 'multiple'"));
            }

            break;

        case PlayoutMode.Duration:
            if (item.PlayoutDuration is null)
            {
                return(BaseError.New("[PlayoutDuration] is required for playout mode 'duration'"));
            }

            if (item.TailMode == TailMode.Filler && item.TailFillerId == null)
            {
                return(BaseError.New("Tail Filler is required with tail mode Filler"));
            }

            if (item.TailFillerId != null && item.TailMode != TailMode.Filler)
            {
                return(BaseError.New("Tail Filler will not be used unless tail mode is set to Filler"));
            }

            break;

        default:
            return(BaseError.New("[PlayoutMode] is invalid"));
        }

        return(programSchedule);
    }
 protected ProgramScheduleItem BuildItem(
     ProgramSchedule programSchedule,
     int index,
     IProgramScheduleItemRequest item) =>
 item.PlayoutMode switch
 {