'use strict';

/**
 * Extrait une image de chaque vidéo pour en faire des vignettes.
 *
 * @license https://www.gnu.org/licenses/gpl-3.0.html
 * @link https://www.igalerie.org/
 */
function VideoCaptures(captures)
{
	// Position initiale pour l'extraction d'une image de la vidéo.
	// Une valeur de 0.5 signifie que l'on va extraire une image au milieu de la vidéo.
	const _positionInitial = 0.5;

	// Raccourci pour document.querySelector().
	const _q = selector => { return document.querySelector(selector); };



	// Durée de la vidéo.
	var _duration;

	// Position pour l'extraction d'une image de la vidéo.
	var _position = _positionInitial;

	// Hauteur de la vidéo en pixels.
	var _height;

	// Index de la vidéo courante.
	var _i = 0;

	// Élément de la vidéo.
	var _video;

	// Largeur de la vidéo en pixels.
	var _width;



	/**
	 * Initialisation.
	 *
	 * @return void
	 */
	(function()
	{
		if (captures.length)
		{
			_insertVideo();
		}
	})();



	/**
	 * Gestionnaire de l'événement "canplaythrough".
	 *
	 * @return void
	 */
	function _canplaythrough()
	{
		_duration = Math.round(_video.duration);
		_width = _video.videoWidth;
		_height = _video.videoHeight;

		// Si la vidéo n'est pas valide, on passe à la suivante.
		if (_height < 1 || _width < 1)
		{
			console.log('Invalid size');
			_i++;
			_position = _positionInitial;
			_insertVideo();
			return;
		}

		_setPosition();
	}

	/**
	 * Gestionnaire d'erreur pour la lecture d'une vidéo.
	 *
	 * @param object evt
	 *
	 * @return void
	 */
	function _error(evt)
	{
		// Message d'erreur.
		console.log('Error: ' + (evt.currentTarget.error.message === undefined
			? 'unknown'
			: evt.currentTarget.error.message));

		// On passe à la vidéo suivante.
		_i++;
		_position = _positionInitial;
		_insertVideo();
	}

	/**
	 * Insertion et lecture d'une vidéo.
	 *
	 * @return void
	 */
	function _insertVideo()
	{
		if (captures[_i] === undefined)
		{
			return;
		}

		const path = captures[_i].path.replace(/&amp;/g, '&');
		const rand = Math.random().toString().replace('.', '');

		// Création de la vidéo.
		_video = document.createElement('video');
		_video.muted = true;

		// Gestionnaires d'événements.
		_video.addEventListener('canplaythrough', _canplaythrough);
		_video.addEventListener('error', _error);

		// Chargement de la vidéo.
		const source = document.createElement('source');
		source.src = path + '&rand=' + rand;
		source.type = 'video/mp4';
		_video.insertAdjacentElement('beforeend', source);
	}

	/**
	 * Extrait une image de la vidéo, puis l'envoi au serveur.
	 *
	 * @return void
	 */
	function _getFrame()
	{
		_video.removeEventListener('canplay', _getFrame);

		const maxsize = 1920;
		const canvas = document.createElement('canvas');
		canvas.width = _width;
		canvas.height = _height;

		if (_width > maxsize || _height > maxsize)
		{
			if (_width < _height)
			{
				canvas.width = Math.round((maxsize / _height) * _width);
				canvas.height = maxsize;
			}
			else
			{
				canvas.height = Math.round((maxsize / _width) * _height);
				canvas.width = maxsize;
			}
		}
		canvas.getContext('2d').drawImage(_video, 0, 0, canvas.width, canvas.height);
		_video.remove();

		let canvas_data = canvas.toDataURL('image/jpeg');
		canvas_data = canvas_data.replace(/^data:image\/jpeg;base64,/, '');

		// Si l'image extraite est peu volumineuse,
		// c'est qu'il y a de fortes chances qu'elle soit trop uniforme
		// (trop sombre ou trop claire).
		// On tente donc d'extraire une image à un autre endroit de la vidéo
		// de manière à ce qu'elle soit plus représentative.
		if (canvas_data.length < (maxsize * 33))
		{
			if (_position > 0.4)
			{
				_position = _positionInitial / 1.5;
				_setPosition();
				return;
			}
			if (_position > 0.3)
			{
				_position = _positionInitial / 2;
				_setPosition();
				return;
			}
		}

		// Envoi de l'image et des informations au serveur.
		const path = typeof GALLERY != 'undefined' ? GALLERY.path : gallery_path;
		const csrf = typeof GALLERY != 'undefined' ? GALLERY.anticsrf : anticsrf;
		const xhr = new XMLHttpRequest();
		xhr.addEventListener('loadend', () =>
		{
			if (typeof xhr.response == 'object' && xhr.response?.success)
			{
				// Mise à jour des vignettes.
				_updateThumb();

				// Vidéo suivante.
				_i++;
				_position = _positionInitial;
				_insertVideo();
			}
		});
		xhr.open('POST', path + '/capture.php');
		xhr.setRequestHeader('Content-type', 'application/json');
		xhr.responseType = 'json';
		xhr.send(JSON.stringify(
		{
			anticsrf: csrf,
			hash: captures[_i].hash,
			data: canvas_data,
			duration: _duration,
			height: _height,
			id: captures[_i].id,
			key: captures[_i].key,
			width: _width
		}));
	}

	/**
	 * Définit la position de lecture, puis déclenche la capture d'image.
	 *
	 * @return void
	 */
	function _setPosition()
	{
		_video.removeEventListener('canplaythrough', _canplaythrough);
		_video.removeEventListener('error', _error);
		_video.currentTime = _duration * _position;
		_video.addEventListener('canplay', _getFrame);
	}

	/**
	 * Met à jour les informations de la vidéo si elle est présente sur la page.
	 *
	 * @return void
	 */
	function _updateThumb()
	{
		let id = captures[_i].id;

		if (_q('body').id == 'section_items_pending')
		{
			id = id.replace(/p/, '');
		}

		const get_new_thumb_src = img => img.src.replace(/.+video-no-thumb\.png\#(.+)$/, '$1');

		// Informations.
		const img = _q(`img[data-video-id="${id}"]`);
		if (img && img.src.match(/video-no-thumb\.png\#/))
		{
			const thumb_src = get_new_thumb_src(img);

			// Durée.
			const c = d => { return Math.round(d).toString().padStart(2, '0'); };
			const duration_short = c(_duration/60%60) + ':' + c(_duration%60);
			const duration = _duration >= 3600
				? c(_duration/3600) + ':' + duration_short
				: duration_short;
			if (_duration > 0)
			{
				_q('#videoduration_' + id).textContent = duration;
			}

			// Admin : attributs de la vidéo (preview).
			const preview_maxsize = 400;
			let preview_w = _width, preview_h = _height;
			if (_width > preview_maxsize || _height > preview_maxsize)
			{
				if (_width < _height)
				{
					preview_w = Math.round((preview_maxsize / _height) * _width);
					preview_h = preview_maxsize;
				}
				else
				{
					preview_w = preview_maxsize;
					preview_h = Math.round((preview_maxsize / _width) * _height);
				}
			}
			const video = _q(`video[data-video-id="${id}"]`);
			if (video)
			{
				video.setAttribute('poster', thumb_src);
				video.setAttribute('width', preview_w);
				video.setAttribute('height', preview_h);
			}

			// Admin : mode d'affichage en liste.
			const obj_stats = _q('#obj_fold_stats_' + id);
			if (obj_stats)
			{
				// Dimensions.
				obj_stats.querySelector('tr:nth-child(3) td.num').textContent
					= _width + ' x ' + _height + ' ' + l10n_pixels;

				// Durée.
				obj_stats.querySelector('tr:nth-child(4) td.num').textContent = duration;
			}

			// Admin : mode d'affichage en grille.
			if (_q('#obj_grid_container'))
			{
				const grid_img = _q(`#obj_grid_container img[data-video-id="${id}"]`);

				// Dimensions.
				if (_width > 0 && _height > 0)
				{
					// Vignette.
					if (grid_img)
					{
						grid_img.setAttribute('data-width', _width);
						grid_img.setAttribute('data-height', _height);
						grid_img.setAttribute('data-preview-width', preview_w);
						grid_img.setAttribute('data-preview-height', preview_h);
					}

					// Panneau d'informations.
					const panel_size = _q(
						`#obj_panel_infos[data-id="${id}"] #obj_panel_stats_size span`
					);
					if (panel_size)
					{
						panel_size.textContent = _width + ' x ' + _height + ' ' + l10n_pixels;
					}
				}

				// Durée.
				if (_duration)
				{
					// Vignette.
					if (grid_img)
					{
						grid_img.setAttribute('data-duration', duration);
					}

					// Panneau d'informations.
					const panel_duration = _q(
						`#obj_panel_infos[data-id="${id}"] #obj_panel_stats_duration span`
					);
					if (panel_duration)
					{
						panel_duration.textContent = duration;
					}
				}
			}
		}

		// Vignettes.
		document.querySelectorAll(`img[data-video-id="${id}"]`).forEach(
			elem => elem.setAttribute('src', get_new_thumb_src(elem))
		);
	}
};