import React, { useMemo, useRef, useState } from "react";
import { Alert, TouchableOpacity, View } from "react-native";
import { Text } from "@/components/common/Text";
import { Loader } from "@/components/Loader";
import { Feather, Ionicons } from "@expo/vector-icons";
import { RoundButton } from "@/components/RoundButton";

import {
  CastButton,
  CastContext,
  MediaStatus,
  RemoteMediaClient,
  useStreamPosition,
} from "react-native-google-cast";
import { useCallback, useEffect } from "react";
import { Platform } from "react-native";
import { Image } from "expo-image";
import { Slider } from "react-native-awesome-slider";
import {
  runOnJS,
  SharedValue,
  useAnimatedReaction,
  useSharedValue,
} from "react-native-reanimated";
import { debounce } from "lodash";
import { useSettings } from "@/utils/atoms/settings";
import { useHaptic } from "@/hooks/useHaptic";
import { writeToLog } from "@/utils/log";
import { formatTimeString } from "@/utils/time";
import SkipButton from "@/components/video-player/controls/SkipButton";
import NextEpisodeCountDownButton from "@/components/video-player/controls/NextEpisodeCountDownButton";
import { useIntroSkipper } from "@/hooks/useIntroSkipper";
import { useCreditSkipper } from "@/hooks/useCreditSkipper";
import { useAdjacentItems } from "@/hooks/useAdjacentEpisodes";
import { useTrickplay } from "@/hooks/useTrickplay";
import { secondsToTicks } from "@/utils/secondsToTicks";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
import { chromecastLoadMedia } from "@/utils/chromecastLoadMedia";
import { useAtomValue } from "jotai";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { getParentBackdropImageUrl } from "@/utils/jellyfin/image/getParentBackdropImageUrl";
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
import { chromecast as chromecastProfile } from "@/utils/profiles/chromecast";
import { SelectedOptions } from "./ItemContent";
import {
  getDefaultPlaySettings,
  previousIndexes,
} from "@/utils/jellyfin/getDefaultPlaySettings";
import { useQuery } from "@tanstack/react-query";
import {
  getPlaystateApi,
  getUserLibraryApi,
} from "@jellyfin/sdk/lib/utils/api";
import { useTranslation } from "react-i18next";
import { Colors } from "@/constants/Colors";
import { useRouter } from "expo-router";
import { ParallaxScrollView } from "@/components/ParallaxPage";
import { ItemImage } from "@/components/common/ItemImage";
import { BitrateSelector } from "@/components/BitrateSelector";
import { ItemHeader } from "@/components/ItemHeader";
import { MediaSourceSelector } from "@/components/MediaSourceSelector";
import { AudioTrackSelector } from "@/components/AudioTrackSelector";
import { SubtitleTrackSelector } from "@/components/SubtitleTrackSelector";
import { ItemTechnicalDetails } from "@/components/ItemTechnicalDetails";
import { OverviewText } from "@/components/OverviewText";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { PlayedStatus } from "./PlayedStatus";
import { AddToFavorites } from "./AddToFavorites";

export default function ChromecastControls({
  mediaStatus,
  client,
  setWasMediaPlaying,
  reportPlaybackStopedRef,
}: {
  mediaStatus: MediaStatus;
  client: RemoteMediaClient;
  setWasMediaPlaying: (wasPlaying: boolean) => void;
  reportPlaybackStopedRef: React.MutableRefObject<() => void>;
}) {
  const lightHapticFeedback = useHaptic("light");

  const api = useAtomValue(apiAtom);
  const user = useAtomValue(userAtom);

  const { settings } = useSettings();

  const [currentTime, setCurrentTime] = useState(0);
  const [remainingTime, setRemainingTime] = useState(Infinity);
  const max = useSharedValue(mediaStatus.mediaInfo?.streamDuration || 0);

  const streamPosition = useStreamPosition();
  const progress = useSharedValue(streamPosition || 0);

  const wasPlayingRef = useRef(false);

  const isSeeking = useSharedValue(false);
  const isPlaying = useMemo(
    () => mediaStatus.playerState === "playing",
    [mediaStatus.playerState]
  );
  const isBufferingOrLoading = useMemo(
    () =>
      mediaStatus.playerState === null ||
      mediaStatus.playerState === "buffering" ||
      mediaStatus.playerState === "loading",
    [mediaStatus.playerState]
  );

  // request update of media status every player state change
  useEffect(() => {
    client.requestStatus();
  }, [mediaStatus.playerState]);

  // update max progress
  useEffect(() => {
    if (mediaStatus.mediaInfo?.streamDuration)
      max.value = mediaStatus.mediaInfo?.streamDuration;
  }, [mediaStatus.mediaInfo?.streamDuration]);

  const updateTimes = useCallback(
    (currentProgress: number, maxValue: number) => {
      setCurrentTime(currentProgress);
      setRemainingTime(maxValue - currentProgress);
    },
    []
  );

  useAnimatedReaction(
    () => ({
      progress: progress.value,
      max: max.value,
      isSeeking: isSeeking.value,
    }),
    (result) => {
      if (result.isSeeking === false) {
        runOnJS(updateTimes)(result.progress, result.max);
      }
    },
    [updateTimes]
  );

  const { mediaMetadata, itemId, streamURL } = useMemo(
    () => ({
      mediaMetadata: mediaStatus.mediaInfo?.metadata,
      itemId: mediaStatus.mediaInfo?.contentId,
      streamURL: mediaStatus.mediaInfo?.contentUrl,
    }),
    [mediaStatus]
  );

  const type = useMemo(
    () => mediaMetadata?.type || "generic",
    [mediaMetadata?.type]
  );
  const images = useMemo(
    () => mediaMetadata?.images || [],
    [mediaMetadata?.images]
  );

  const { playbackOptions, sessionId, mediaSourceId } = useMemo(() => {
    const mediaCustomData = mediaStatus.mediaInfo?.customData as
      | {
          playbackOptions: SelectedOptions;
          sessionId?: string;
          mediaSourceId?: string;
        }
      | undefined;

    return (
      mediaCustomData || {
        playbackOptions: undefined,
        sessionId: undefined,
        mediaSourceId: undefined,
      }
    );
  }, [mediaStatus.mediaInfo?.customData]);

  const {
    data: item,
    // currently nothing is indicating that item is loading, because most of the time it loads very fast
    isLoading: isLoadingItem,
    isError: isErrorItem,
    error,
    refetch,
  } = useQuery({
    queryKey: ["item", itemId],
    queryFn: async () => {
      if (!itemId) return;
      const res = await getUserLibraryApi(api!).getItem({
        itemId,
        userId: user?.Id,
      });

      return res.data;
    },
    enabled: !!itemId,
    staleTime: 0,
  });

  const onProgress = useCallback(
    async (progressInTicks: number, isPlaying: boolean) => {
      if (!item?.Id || !streamURL) return;

      await getPlaystateApi(api!).onPlaybackProgress({
        itemId: item.Id,
        audioStreamIndex: playbackOptions?.audioIndex,
        subtitleStreamIndex: playbackOptions?.subtitleIndex,
        mediaSourceId,
        positionTicks: Math.floor(progressInTicks),
        isPaused: !isPlaying,
        playMethod: streamURL.includes("m3u8") ? "Transcode" : "DirectStream",
        playSessionId: sessionId,
      });
    },
    [api, item, playbackOptions, mediaSourceId, streamURL, sessionId]
  );

  // update progess on stream position change
  useEffect(() => {
    if (streamPosition) {
      progress.value = streamPosition;
      onProgress(secondsToTicks(streamPosition), isPlaying);
    }
  }, [streamPosition, isPlaying]);

  const reportPlaybackStart = useCallback(async () => {
    if (!streamURL) return;

    await getPlaystateApi(api!).onPlaybackStart({
      itemId: item?.Id!,
      audioStreamIndex: playbackOptions?.audioIndex,
      subtitleStreamIndex: playbackOptions?.subtitleIndex,
      mediaSourceId,
      playMethod: streamURL.includes("m3u8") ? "Transcode" : "DirectStream",
      playSessionId: sessionId,
    });
  }, [api, item, playbackOptions, mediaSourceId, streamURL, sessionId]);

  // report playback started
  useEffect(() => {
    setWasMediaPlaying(true);
    reportPlaybackStart();
  }, [reportPlaybackStart]);

  // update the reportPlaybackStoppedRef
  useEffect(() => {
    reportPlaybackStopedRef.current = async () => {
      if (!streamURL) return;

      await getPlaystateApi(api!).onPlaybackStopped({
        itemId: item?.Id!,
        mediaSourceId,
        positionTicks: secondsToTicks(progress.value),
        playSessionId: sessionId,
      });
    };
  }, [
    api,
    item,
    playbackOptions,
    progress,
    mediaSourceId,
    streamURL,
    sessionId,
  ]);

  const { previousItem, nextItem } = useAdjacentItems({
    item: {
      Id: itemId,
      SeriesId: item?.SeriesId,
      Type: item?.Type,
    },
  });

  const goToItem = useCallback(
    async (item: BaseItemDto) => {
      if (!api) {
        console.warn("Failed to go to item: No api!");
        return;
      }

      const previousIndexes: previousIndexes = {
        subtitleIndex: playbackOptions?.subtitleIndex || undefined,
        audioIndex: playbackOptions?.audioIndex || undefined,
      };

      const {
        mediaSource,
        audioIndex: defaultAudioIndex,
        subtitleIndex: defaultSubtitleIndex,
      } = getDefaultPlaySettings(item, settings, previousIndexes, undefined);

      // Get a new URL with the Chromecast device profile:
      const data = await getStreamUrl({
        api,
        item,
        deviceProfile: chromecastProfile,
        startTimeTicks: item?.UserData?.PlaybackPositionTicks!,
        userId: user?.Id,
        audioStreamIndex: defaultAudioIndex,
        // maxStreamingBitrate: playbackOptions.bitrate?.value,   // TODO handle bitrate limit
        subtitleStreamIndex: defaultSubtitleIndex,
        mediaSourceId: mediaSource?.Id,
      });

      if (!data?.url) {
        console.warn("No URL returned from getStreamUrl", data);
        Alert.alert("Client error", "Could not create stream for Chromecast");
        return;
      }

      await chromecastLoadMedia({
        client,
        item,
        contentUrl: data.url,
        sessionId: data.sessionId || undefined,
        mediaSourceId: data.mediaSource?.Id || undefined,
        playbackOptions,
        images: [
          {
            url: getParentBackdropImageUrl({
              api,
              item,
              quality: 90,
              width: 2000,
            })!,
          },
        ],
      });

      await client.requestStatus();
    },
    [client, api]
  );

  const goToNextItem = useCallback(() => {
    if (!nextItem) {
      console.warn("Failed to skip to next item: No next item!");
      return;
    }
    lightHapticFeedback();
    goToItem(nextItem);
  }, [nextItem, lightHapticFeedback]);

  const goToPreviousItem = useCallback(() => {
    if (!previousItem) {
      console.warn("Failed to skip to next item: No next item!");
      return;
    }
    lightHapticFeedback();
    goToItem(previousItem);
  }, [previousItem, lightHapticFeedback]);

  const pause = useCallback(() => {
    client.pause();
  }, [client]);

  const play = useCallback(() => {
    client.play();
  }, [client]);

  const seek = useCallback(
    (time: number) => {
      // skip to next episode if seeking to end (for credit skipping)
      // with 1 second room to react
      if (nextItem && time >= max.value - 1) {
        goToNextItem();
        return;
      }
      client.seek({
        position: time,
      });
    },
    [client, goToNextItem, nextItem, max]
  );

  const togglePlay = useCallback(() => {
    if (isPlaying) pause();
    else play();
  }, [isPlaying, play, pause]);

  const handleSkipBackward = useCallback(async () => {
    if (!settings?.rewindSkipTime) return;
    wasPlayingRef.current = isPlaying;
    lightHapticFeedback();
    try {
      const curr = progress.value;
      if (curr !== undefined) {
        const newTime = Math.max(0, curr - settings.rewindSkipTime);
        seek(newTime);
        if (wasPlayingRef.current === true) play();
      }
    } catch (error) {
      writeToLog("ERROR", "Error seeking video backwards", error);
    }
  }, [settings, isPlaying]);

  const handleSkipForward = useCallback(async () => {
    if (!settings?.forwardSkipTime) return;
    wasPlayingRef.current = isPlaying;
    lightHapticFeedback();
    try {
      const curr = progress.value;
      if (curr !== undefined) {
        const newTime = curr + settings.forwardSkipTime;
        seek(Math.max(0, newTime));
        if (wasPlayingRef.current === true) play();
      }
    } catch (error) {
      writeToLog("ERROR", "Error seeking video forwards", error);
    }
  }, [settings, isPlaying]);

  const { showSkipButton, skipIntro } = useIntroSkipper(
    itemId,
    currentTime,
    seek,
    play,
    false
  );

  const { showSkipCreditButton, skipCredit } = useCreditSkipper(
    itemId,
    currentTime,
    seek,
    play,
    false
  );

  // Android requires the cast button to be present for startDiscovery to work
  const AndroidCastButton = useCallback(
    () =>
      Platform.OS === "android" ? (
        <CastButton tintColor="transparent" />
      ) : (
        <></>
      ),
    [Platform.OS]
  );

  const TrickplaySliderMemoized = useMemo(
    () => (
      <TrickplaySlider
        item={item}
        progress={progress}
        wasPlayingRef={wasPlayingRef}
        isPlaying={isPlaying}
        isSeeking={isSeeking}
        range={{ max }}
        play={play}
        pause={pause}
        seek={seek}
      />
    ),
    [
      item,
      progress,
      wasPlayingRef,
      isPlaying,
      isSeeking,
      max,
      play,
      pause,
      seek,
    ]
  );

  const NextEpisodeButtonMemoized = useMemo(
    () => (
      <NextEpisodeCountDownButton
        show={nextItem !== null && max.value > 0 && remainingTime < 10}
        onFinish={goToNextItem}
        onPress={goToNextItem}
      />
    ),
    [nextItem, max, remainingTime, goToNextItem]
  );

  const { t } = useTranslation();
  const router = useRouter();

  const insets = useSafeAreaInsets();

  const [loadingLogo, setLoadingLogo] = useState(true);
  const [headerHeight, setHeaderHeight] = useState(350);

  const logoUrl = useMemo(() => images[0]?.url, [images]);

  if (isErrorItem) {
    return (
      <View className="w-full h-full flex flex-col items-center justify-center bg-black">
        <View className="p-12 flex gap-4">
          <Text className="text-center font-semibold text-red-500 text-lg">
            {t("chromecast.error_loading_item")}
          </Text>
          {error && (
            <Text className="text-center opacity-80">{error.message}</Text>
          )}
        </View>
        <View className="flex gap-2 mt-auto mb-20">
          <TouchableOpacity
            className="flex flex-row items-center justify-center gap-2"
            onPress={() => refetch()}
          >
            <Ionicons name="reload" size={24} color={Colors.primary} />
            <Text className="ml-2 text-purple-600 text-lg">
              {t("chromecast.retry_load_item")}
            </Text>
          </TouchableOpacity>
          <TouchableOpacity
            className="flex flex-row items-center justify-center gap-2"
            onPress={() => {
              router.push("/(auth)/(home)/");
            }}
          >
            <Ionicons name="home" size={16} color={Colors.text} />
            <Text className="ml-2 text-white text-sm underline">
              {t("chromecast.go_home")}
            </Text>
          </TouchableOpacity>
        </View>
      </View>
    );
  }

  if (!item) {
    return <Text>Do something when item is undefined</Text>;
  }

  if (!playbackOptions) {
    return <Text>Do something when playbackOptions is undefined</Text>;
  }

  return (
    <View
      className="flex-1 relative"
      style={{
        paddingLeft: insets.left,
        paddingRight: insets.right,
      }}
    >
      {/* TODO do navigation header properly */}
      <View
        className="flex flex-row justify-between absolute w-full top-2 z-50"
        style={{
          paddingLeft: insets.left,
          paddingRight: insets.right,
        }}
      >
        <RoundButton size="large" icon="arrow-back" />
        {item.Type !== "Program" && (
          <View className="flex flex-row items-center space-x-2">
            <RoundButton
              size="large"
              onPress={() => {
                CastContext.showCastDialog();
              }}
            >
              <AndroidCastButton />
              <Feather name="cast" size={24} color={"white"} />
            </RoundButton>
            <PlayedStatus items={[item]} size="large" />
            <AddToFavorites item={item} />
          </View>
        )}
      </View>
      <ParallaxScrollView
        className={`flex-1 ${loadingLogo ? "opacity-0" : "opacity-100"}`}
        headerHeight={headerHeight}
        headerImage={
          <View style={[{ flex: 1 }]}>
            <ItemImage
              variant={
                item.Type === "Movie" && logoUrl ? "Backdrop" : "Primary"
              }
              item={item}
              style={{
                width: "100%",
                height: "100%",
              }}
            />
          </View>
        }
        logo={
          <>
            {logoUrl ? (
              <Image
                source={{
                  uri: logoUrl,
                }}
                style={{
                  height: 130,
                  width: "100%",
                  resizeMode: "contain",
                }}
                onLoad={() => setLoadingLogo(false)}
                onError={() => setLoadingLogo(false)}
              />
            ) : null}
          </>
        }
      >
        <View className="flex flex-col bg-transparent shrink">
          <View className="flex flex-col px-4 w-full space-y-2 pt-2 mb-2 shrink">
            <ItemHeader item={item} className="mb-4" />
            {item.Type !== "Program" && !Platform.isTV && (
              <View className="flex flex-row items-center justify-start w-full h-16">
                <BitrateSelector
                  className="mr-1"
                  onChange={(val) =>
                    // setSelectedOptions(
                    //   (prev) => prev && { ...prev, bitrate: val }
                    // )
                    console.log("new selected options", val)
                  }
                  selected={playbackOptions.bitrate}
                />
                <MediaSourceSelector
                  className="mr-1"
                  item={item}
                  onChange={(val) =>
                    // setSelectedOptions((prev) =>
                    //   prev && {
                    //     ...prev,
                    //     mediaSource: val,
                    //   }
                    // )
                    console.log("new selected options", val)
                  }
                  selected={playbackOptions.mediaSource}
                />
                <AudioTrackSelector
                  className="mr-1"
                  source={playbackOptions.mediaSource}
                  onChange={(val) => {
                    // setSelectedOptions((prev) =>
                    //   prev && {
                    //     ...prev,
                    //     audioIndex: val,
                    //   }
                    // );
                    console.log("new selected options", val);
                  }}
                  selected={playbackOptions.audioIndex}
                />
                <SubtitleTrackSelector
                  source={playbackOptions.mediaSource}
                  onChange={(val) =>
                    // setSelectedOptions(
                    //   (prev) =>
                    //     prev && {
                    //       ...prev,
                    //       subtitleIndex: val,
                    //     }
                    // )
                    console.log("new selected options", val)
                  }
                  selected={playbackOptions.subtitleIndex}
                />
              </View>
            )}
          </View>
          <ItemTechnicalDetails source={playbackOptions.mediaSource} />
          <OverviewText text={item.Overview} className="px-4 mb-4" />
        </View>
      </ParallaxScrollView>
      <View className="pt-2">
        {TrickplaySliderMemoized}
        <View className="flex flex-row items-center justify-between mt-2">
          <Text className="text-[12px] text-neutral-400">
            {formatTimeString(currentTime, "s")}
          </Text>
          <Text className="text-[12px] text-neutral-400">
            -{formatTimeString(remainingTime, "s")}
          </Text>
        </View>
        <View className="flex flex-row w-full items-center justify-evenly mt-2 mb-10">
          <TouchableOpacity onPress={goToPreviousItem} disabled={!previousItem}>
            <Ionicons
              name="play-skip-back-outline"
              size={30}
              color={previousItem ? "white" : "gray"}
            />
          </TouchableOpacity>
          <TouchableOpacity onPress={handleSkipBackward}>
            <Ionicons name="play-back-outline" size={30} color="white" />
          </TouchableOpacity>
          <TouchableOpacity
            onPress={() => togglePlay()}
            className="flex w-14 h-14 items-center justify-center"
          >
            {!isBufferingOrLoading ? (
              <Ionicons
                name={isPlaying ? "pause" : "play"}
                size={50}
                color="white"
              />
            ) : (
              <Loader size={"large"} />
            )}
          </TouchableOpacity>
          <TouchableOpacity onPress={handleSkipForward}>
            <Ionicons name="play-forward-outline" size={30} color="white" />
          </TouchableOpacity>
          <TouchableOpacity onPress={goToNextItem} disabled={!nextItem}>
            <Ionicons
              name="play-skip-forward-outline"
              size={30}
              color={nextItem ? "white" : "gray"}
            />
          </TouchableOpacity>
        </View>
      </View>
      {/* TODO find proper placement for these buttons */}
      {/* <View className="flex flex-row w-full justify-end px-6 pb-6">
        <SkipButton
          showButton={showSkipButton}
          onPress={skipIntro}
          buttonText="Skip Intro"
        />
        <SkipButton
          showButton={showSkipCreditButton}
          onPress={skipCredit}
          buttonText="Skip Credits"
        />
        {NextEpisodeButtonMemoized}
      </View> */}
    </View>
  );
}

type TrickplaySliderProps = {
  item?: BaseItemDto;
  progress: SharedValue<number>;
  wasPlayingRef: React.MutableRefObject<boolean>;
  isPlaying: boolean;
  isSeeking: SharedValue<boolean>;
  range: { min?: SharedValue<number>; max: SharedValue<number> };
  play: () => void;
  pause: () => void;
  seek: (time: number) => void;
};

function TrickplaySlider({
  item,
  progress,
  wasPlayingRef,
  isPlaying,
  isSeeking,
  range,
  play,
  pause,
  seek,
}: TrickplaySliderProps) {
  const [isSliding, setIsSliding] = useState(false);
  const lastProgressRef = useRef<number>(0);

  const min = useSharedValue(range.min?.value || 0);

  const {
    trickPlayUrl,
    calculateTrickplayUrl,
    trickplayInfo,
    prefetchAllTrickplayImages,
  } = useTrickplay(
    {
      Id: item?.Id,
      RunTimeTicks: secondsToTicks(progress.value),
      Trickplay: item?.Trickplay,
    },
    true
  );

  useEffect(() => {
    prefetchAllTrickplayImages();
  }, []);

  const handleSliderStart = useCallback(() => {
    setIsSliding(true);
    wasPlayingRef.current = isPlaying;
    lastProgressRef.current = progress.value;

    pause();
    isSeeking.value = true;
  }, [isPlaying]);

  const handleSliderComplete = useCallback(async (value: number) => {
    isSeeking.value = false;
    progress.value = value;
    setIsSliding(false);

    seek(Math.max(0, Math.floor(value)));
    if (wasPlayingRef.current === true) play();
  }, []);

  const [time, setTime] = useState({ hours: 0, minutes: 0, seconds: 0 });
  const handleSliderChange = useCallback(
    debounce((value: number) => {
      calculateTrickplayUrl(secondsToTicks(value));
      const progressInSeconds = Math.floor(value);
      const hours = Math.floor(progressInSeconds / 3600);
      const minutes = Math.floor((progressInSeconds % 3600) / 60);
      const seconds = progressInSeconds % 60;
      setTime({ hours, minutes, seconds });
    }, 3),
    []
  );

  const memoizedRenderBubble = useCallback(() => {
    if (!trickPlayUrl || !trickplayInfo) {
      return null;
    }
    const { x, y, url } = trickPlayUrl;
    const tileWidth = 150;
    const tileHeight = 150 / trickplayInfo.aspectRatio!;

    return (
      <View
        style={{
          position: "absolute",
          left: -62,
          bottom: 0,
          paddingTop: 30,
          paddingBottom: 5,
          width: tileWidth * 1.5,
          justifyContent: "center",
          alignItems: "center",
        }}
      >
        <View
          style={{
            width: tileWidth,
            height: tileHeight,
            alignSelf: "center",
            transform: [{ scale: 1.4 }],
            borderRadius: 5,
          }}
          className="bg-neutral-800 overflow-hidden"
        >
          <Image
            cachePolicy={"memory-disk"}
            style={{
              width: 150 * trickplayInfo?.data.TileWidth!,
              height:
                (150 / trickplayInfo.aspectRatio!) *
                trickplayInfo?.data.TileHeight!,
              transform: [
                { translateX: -x * tileWidth },
                { translateY: -y * tileHeight },
              ],
              resizeMode: "cover",
            }}
            source={{ uri: url }}
            contentFit="cover"
          />
        </View>
        <Text
          style={{
            marginTop: 30,
            fontSize: 16,
          }}
        >
          {`${time.hours > 0 ? `${time.hours}:` : ""}${
            time.minutes < 10 ? `0${time.minutes}` : time.minutes
          }:${time.seconds < 10 ? `0${time.seconds}` : time.seconds}`}
        </Text>
      </View>
    );
  }, [trickPlayUrl, trickplayInfo, time]);

  return (
    <Slider
      theme={{
        maximumTrackTintColor: "rgba(255,255,255,0.2)",
        minimumTrackTintColor: "#fff",
        cacheTrackTintColor: "rgba(255,255,255,0.3)",
        bubbleBackgroundColor: "#fff",
        bubbleTextColor: "#666",
        heartbeatColor: "#999",
      }}
      renderThumb={() => null}
      onSlidingStart={handleSliderStart}
      onSlidingComplete={handleSliderComplete}
      onValueChange={handleSliderChange}
      containerStyle={{
        borderRadius: 100,
      }}
      renderBubble={() => isSliding && memoizedRenderBubble()}
      sliderHeight={10}
      thumbWidth={0}
      progress={progress}
      minimumValue={min}
      maximumValue={range.max}
    />
  );
}
