import {useNavigate, useParams, useSearchParams} from "react-router-dom";
import {useEffect, useState, useRef, useCallback} from "react";
import Navbar from "../components/Navbar.jsx";
import { useAuth } from "../contexts/AuthContext.jsx";
import Comment from "../components/Comment.jsx";
import VideoCard from "../components/VideoCard.jsx";
import Tag from "../components/Tag.jsx";
import {addView, getSimilarVideos, getVideoById, toggleLike} from "../services/video.service.js";
import {subscribe} from "../services/channel.service.js";
import {addComment} from "../services/comment.service.js";
import { getPlaylists } from "../services/user.service.js";
import { addToPlaylist, getPlaylistById } from "../services/playlist.service.js";
import PlaylistVideoCard from "../components/PlaylistVideoCard.jsx";
export default function Video() {
const {id} = useParams();
const { user, isAuthenticated } = useAuth();
const videoRef = useRef(null);
const controllerRef = useRef(null);
const navigation = useNavigate();
const [searchParams] = useSearchParams();
const playlistId = searchParams.get("playlistId");
const isPlaylist = playlistId !== null;
const [video, setVideo] = useState(null);
const [nextVideo, setNextVideo] = useState(null);
const [similarVideos, setSimilarVideos] = useState([]);
const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(0);
const [progress, setProgress] = useState(0);
const [showControls, setShowControls] = useState(false);
const [comment, setComment] = useState("");
const [alerts, setAlerts] = useState([]);
const [playlists, setPlaylists] = useState([]);
const [isAddToPlaylistOpen, setIsAddToPlaylistOpen] = useState(false);
const [currentPlaylist, setCurrentPlaylist] = useState(null);
const fetchVideo = useCallback(async () => {
// Fetch video data and similar videos based on the video ID from the URL
if (!id) {
addAlert('error', 'Vidéo introuvable');
navigation('/');
return;
}
const data = await getVideoById(id, addAlert);
if (!data) return;
setVideo(data);
const similarVideosResponse = await getSimilarVideos(id, addAlert);
if (similarVideosResponse) {
setSimilarVideos(similarVideosResponse);
}
// Add views to the video
await addView(id, addAlert);
}, [id, navigation]);
const fetchPlaylists = async () => {
const token = localStorage.getItem('token');
if (!token) return;
const user = JSON.parse(localStorage.getItem('user'));
const data = await getPlaylists(user.id, token, addAlert);
if (data) {
setPlaylists(data);
}
}
const fetchCurrentPlaylist = async () => {
const token = localStorage.getItem('token');
if (!token) return;
if (!playlistId) return;
setCurrentPlaylist(await getPlaylistById(playlistId, token, addAlert));
}
const fetchNextVideo = async () => {
const token = localStorage.getItem('token');
if (!token) return;
console.log("Fetching next video");
console.log("currentPlaylist", currentPlaylist);
console.log("current video id from params:", id, "type:", typeof id);
console.log("playlist videos:", currentPlaylist?.videos?.map(v => ({ id: v.id, type: typeof v.id })));
//Find position of current video id in currentPlaylist.videos
const currentIndex = currentPlaylist?.videos.findIndex(video => {
console.log(`Comparing video.id: ${video.id} (${typeof video.id}) with id: ${id} (${typeof id})`);
return video.id.toString() === id.toString();
});
console.log("currentIndex", currentIndex);
if (currentIndex !== -1) {
if (currentPlaylist?.videos[currentIndex + 1]) {
setNextVideo(currentPlaylist.videos[currentIndex + 1]);
console.log("nextVideo", currentPlaylist.videos[currentIndex + 1]);
}
}
}
const passToNextVideo = () => {
if (!nextVideo) {
console.log("No next video available");
return;
}
console.log("Passing to next video:", nextVideo);
// Navigate to the next video with playlist context
if (playlistId) {
navigation(`/video/${nextVideo.id}?playlistId=${playlistId}`);
} else {
navigation(`/video/${nextVideo.id}`);
}
}
useEffect(() => {
fetchVideo();
fetchPlaylists();
fetchCurrentPlaylist();
}, [fetchVideo]);
useEffect(() => {
fetchNextVideo();
}, [currentPlaylist]);
const handlePlayPause = () => {
if (videoRef.current) {
if (videoRef.current.paused) {
videoRef.current.play();
} else {
videoRef.current.pause();
}
}
};
const handleTimeUpdate = () => {
if (videoRef.current) {
const current = videoRef.current.currentTime;
const total = videoRef.current.duration;
setCurrentTime(current);
setDuration(total);
setProgress((current / total) * 100);
}
};
const handleLoadedMetadata = () => {
if (videoRef.current) {
setDuration(videoRef.current.duration);
}
};
const handleTimeBarClick = (event) => {
if (videoRef.current) {
const timeBar = event.currentTarget;
const clickX = event.nativeEvent.offsetX;
const totalWidth = timeBar.offsetWidth;
const percentage = clickX / totalWidth;
const newTime = percentage * duration;
videoRef.current.currentTime = newTime;
setCurrentTime(newTime);
setProgress(percentage * 100);
}
};
const formatTime = (time) => {
if (isNaN(time)) return "0:00";
const minutes = Math.floor(time / 60);
const seconds = Math.floor(time % 60);
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
};
const formatDate = (dateString) => {
if (!dateString) return "";
const months = [
"Janvier", "Février", "Mars", "Avril", "Mai", "Juin",
"Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"
];
const date = new Date(dateString);
const day = date.getDate();
const month = months[date.getMonth()];
const year = date.getFullYear();
return `${day} ${month} ${year}`;
};
const handlePlaying = () => {
if (videoRef.current) {
console.log(`Video is playing at ${videoRef.current.currentTime} seconds`);
}
}
const handleMouseEnter = () => {
setShowControls(true);
};
const handleMouseLeave = () => {
setShowControls(false);
};
const handleSubscribe = async () => {
if (!isAuthenticated) {
navigation('/login');
return;
}
const response = await subscribe(video.creator.id, addAlert);
console.log('Subscription successful:', response);
const subscriptionCount = response.subscriptions || 0;
setVideo((prevVideo) => {
return {
...prevVideo,
creator: {
...prevVideo.creator,
subscribers: subscriptionCount
}
};
})
};
const handleLike = async () => {
if (!isAuthenticated) {
navigation('/login');
return;
}
// Retrieve the token from localStorage
const token = localStorage.getItem('token');
if (!token) {
navigation('/login');
return;
}
const data = await toggleLike(id, token, addAlert);
setVideo((prevVideo) => {
return {
...prevVideo,
likes: data.likes || prevVideo.likes + 1 // Update likes count
};
})
};
const handleComment = async () => {
if (!isAuthenticated) {
navigation('/login');
return;
}
if (!comment.trim()) {
alert("Comment cannot be empty");
return;
}
// Retrieve the token from localStorage
const token = localStorage.getItem('token');
if (!token) {
navigation('/login');
return;
}
const data = await addComment(video.id, comment, token, addAlert);
setComment(""); // Clear the comment input
setVideo((prevVideo) => ({
...prevVideo,
comments: [...(prevVideo.comments || []), data]
}));
}
const addAlert = (type, message) => {
const newAlert = { type, message, id: Date.now() }; // Add unique ID
setAlerts([...alerts, newAlert]);
};
const onCloseAlert = (alertToRemove) => {
setAlerts(alerts.filter(alert => alert !== alertToRemove));
};
const handleAddToPlaylist = async (id) => {
if (!isAuthenticated) {
navigation('/login');
return;
}
const body = {
video: video.id
}
const token = localStorage.getItem('token');
await addToPlaylist(id, body, token, addAlert);
setIsAddToPlaylistOpen(!isAddToPlaylistOpen);
}
return (
{video ? (
<>
{/* Video player section */}
{/* Video controls */}
{/* Time display */}
{formatTime(currentTime)}
{formatTime(duration)}
{/* Time bar */}
{video.title}
{/* Channel and like */}
{video.creator?.name}
{video.creator?.subscribers || 0} abonnés
{video.likes}
{/* Video details */}
{/* Tags */}
{video.tags && video.tags.length > 0 && (
{video.tags.map((tag, index) => (
))}
)}
{video.views} vues - {formatDate(video.release_date)}
{video.description}
{/* Comments section */}
Commentaires
{/* Comments list */}
{video.comments && video.comments.length > 0 ? (
video.comments.map((comment, index) => (
))
) : (
Aucun commentaire pour le moment. Soyez le premier à en publier !
)}
{/* Similar videos section */}
{
!isPlaylist ? (
{similarVideos.map((video, index) => (
))}
) : (
{currentPlaylist?.name}
{
currentPlaylist?.videos && currentPlaylist.videos.length > 0 ? (
{currentPlaylist.videos.map((video, index) => (
))}
) : (
Aucune vidéo trouvée dans cette playlist.
)
}
)
}
>
): (
Loading
)}
);
}