async def _async_browse_media(
            self,
            source: str,
            camera_id: str,
            event_id: str = None,
            no_descend: bool = True) -> BrowseMediaSource:
        """ actual browse after input validation """
        event: typings.VodEvent = None
        cache: typings.MediaSourceCacheEntry = None
        start_date = None

        if camera_id and camera_id in self.cache:
            cache = self.cache[camera_id]

        if cache and event_id:
            if "playback_events" in cache and event_id in cache[
                    "playback_events"]:
                event = cache["playback_events"][event_id]
                end_date = event["end"]
                start_date = event["start"]
                time = start_date.time()
                duration = end_date - start_date

                title = f"{time} {duration}"
            else:
                year, *rest = event_id.split("/", 3)
                month = rest[0] if len(rest) > 0 else None
                day = rest[1] if len(rest) > 1 else None

                start_date = dt.datetime.combine(
                    dt.date(int(year),
                            int(month) if month else 1,
                            int(day) if day else 1),
                    dt.time.min,
                    dt_utils.now().tzinfo,
                )

                title = f"{start_date.date()}"

            path = f"{source}/{camera_id}/{event_id}"
        else:
            if cache is None:
                camera_id = ""
                title = NAME
            else:
                title = cache["name"]

            path = f"{source}/{camera_id}"

        media_class = MEDIA_CLASS_DIRECTORY if event is None else MEDIA_CLASS_VIDEO

        media = BrowseMediaSource(
            domain=DOMAIN,
            identifier=path,
            media_class=media_class,
            media_content_type=MEDIA_TYPE_VIDEO,
            title=title,
            can_play=bool(not event is None and event.get("file")),
            can_expand=event is None,
        )

        if not event is None and cache.get("playback_thumbnails", False):
            url = "/api/" + DOMAIN + f"/media_proxy/{camera_id}/{event_id}"

            # TODO : I cannot find a way to get the current user context at this point
            #        so I will have to leave the view as unauthenticated, as a temporary
            #        security measure, I will add a unique token to the event to limit
            #        "exposure"
            # url = async_sign_path(self.hass, None, url, dt.timedelta(minutes=30))
            if "token" not in event:
                event["token"] = secrets.token_hex()
            media.thumbnail = f"{url}?token={parse.quote_plus(event['token'])}"

        if not media.can_play and not media.can_expand:
            _LOGGER.debug("Camera %s with event %s without media url found",
                          camera_id, event_id)
            raise IncompatibleMediaSource

        if not media.can_expand or no_descend:
            return media

        media.children = []

        base: ReolinkBase = None

        if cache is None:
            for entry_id in self.hass.data[DOMAIN]:
                entry = self.hass.data[DOMAIN][entry_id]
                if not isinstance(entry, dict) or not BASE in entry:
                    continue
                base = entry[BASE]
                camera_id = base.unique_id
                cache = self.cache.get(camera_id, None)
                if cache is None:
                    cache = self.cache[camera_id] = {
                        "entry_id": entry_id,
                        "unique_id": base.unique_id,
                        "playback_events": {},
                    }
                cache["name"] = base.name

                child = await self._async_browse_media(source, camera_id)
                media.children.append(child)
            return media

        base = self.hass.data[DOMAIN][cache["entry_id"]][BASE]

        # TODO: the cache is one way so over time it can grow and have invalid
        #       records, the code should be expanded to invalidate/expire
        #       entries

        if base is None:
            raise BrowseError("Camera does not exist.")

        if not start_date:
            if ("playback_day_entries" not in cache or
                    cache.get("playback_months", -1) != base.playback_months):
                end_date = dt_utils.now()
                start_date = dt.datetime.combine(end_date.date(), dt.time.min)
                cache["playback_months"] = base.playback_months
                if cache["playback_months"] > 1:
                    start_date -= relativedelta.relativedelta(
                        months=int(cache["playback_months"]))

                entries = cache["playback_day_entries"] = []

                search, _ = await base.api.send_search(start_date, end_date,
                                                       True)

                if not search is None:
                    for status in search:
                        year = status["year"]
                        month = status["mon"]
                        for day, flag in enumerate(status["table"], start=1):
                            if flag == "1":
                                entries.append(dt.date(year, month, day))

                entries.sort()
            else:
                entries = cache["playback_day_entries"]

            for date in cache["playback_day_entries"]:
                child = await self._async_browse_media(
                    source, camera_id, f"{date.year}/{date.month}/{date.day}")
                media.children.append(child)

            return media

        cache["playback_thumbnails"] = base.playback_thumbnails

        end_date = dt.datetime.combine(start_date.date(), dt.time.max,
                                       start_date.tzinfo)

        _, files = await base.api.send_search(start_date, end_date)

        if not files is None:
            events = cache.setdefault("playback_events", {})

            for file in files:
                dto = file["EndTime"]
                end_date = dt.datetime(
                    dto["year"],
                    dto["mon"],
                    dto["day"],
                    dto["hour"],
                    dto["min"],
                    dto["sec"],
                    0,
                    end_date.tzinfo,
                )
                dto = file["StartTime"]
                start_date = dt.datetime(
                    dto["year"],
                    dto["mon"],
                    dto["day"],
                    dto["hour"],
                    dto["min"],
                    dto["sec"],
                    0,
                    end_date.tzinfo,
                )
                event_id = str(start_date.timestamp())
                event = events.setdefault(event_id, {})
                event["start"] = start_date
                event["end"] = end_date
                event["file"] = file["name"]

                child = await self._async_browse_media(source, camera_id,
                                                       event_id)
                media.children.append(child)

        return media
        def create_item(title: str, path: str, thumbnail: bool = False):
            nonlocal self, camera_id, event_id, start_date

            if not title or not path:
                if event_id and "/" in event_id:
                    year, *rest = event_id.split("/", 3)
                    month = rest[0] if len(rest) > 0 else None
                    day = rest[1] if len(rest) > 1 else None

                    start_date = dt.datetime.combine(
                        dt.date(
                            int(year),
                            int(month) if month else 1,
                            int(day) if day else 1,
                        ),
                        dt.time.min,
                        dt_utils.now().tzinfo,
                    )

                    title = f"{start_date.date()}"
                    path = f"{source}/{camera_id}/{event_id}"
                elif base:
                    title = base.name
                    path = f"{source}/{camera_id}"
                else:
                    title = self.name
                    path = source + "/"

            media_class = (MEDIA_CLASS_DIRECTORY if not event_id
                           or "/" in event_id else MEDIA_CLASS_VIDEO)

            media = BrowseMediaSource(
                domain=self.domain,
                identifier=path,
                media_class=media_class,
                media_content_type=MEDIA_TYPE_VIDEO,
                title=title,
                can_play=not bool(media_class == MEDIA_CLASS_DIRECTORY),
                can_expand=bool(media_class == MEDIA_CLASS_DIRECTORY),
            )

            if thumbnail:
                url = THUMBNAIL_URL.format(camera_id=camera_id,
                                           event_id=event_id)
                # cannot do authsign as we are in a websocket and isloated from auth and context
                # we will continue to use custom tokens
                # request = current_request.get()
                # refresh_token_id = request.get(KEY_HASS_REFRESH_TOKEN_ID)
                # if not refresh_token_id:
                #     _LOGGER.debug("no token? %s", list(request.keys()))

                # # leave expiration 30 seconds?
                # media.thumbnail = async_sign_path(
                #     self.hass, refresh_token_id, url, dt.timedelta(seconds=30)
                # )
                media.thumbnail = f"{url}?token={self._short_security_token}"

            if not media.can_play and not media.can_expand:
                _LOGGER.debug(
                    "Camera %s with event %s without media url found",
                    camera_id,
                    event_id,
                )
                raise IncompatibleMediaSource

            return media