/**
 * Custom Fields - field control behavior (media picker + color picker).
 * Loaded on the builder screen and on post/term edit screens.
 */
(function ($) {
	'use strict';

	var cfg = window.wppsCfFields || {};

	function initColorPickers(context) {
		if (typeof $.fn.wpColorPicker !== 'function') {
			return;
		}
		$(context)
			.find('.cf-color-field')
			.not('.wp-color-picker')
			.wpColorPicker();
	}

	function openMediaFrame($wrap) {
		var type = $wrap.data('type') || 'file';
		var $input = $wrap.find('.cf-media__input');
		var $preview = $wrap.find('.cf-media__preview');
		var $clear = $wrap.find('.cf-media__clear');

		var libraryType = type === 'image' ? 'image' : '';
		var frame = wp.media({
			title: type === 'image' ? 'Select Image' : 'Select File',
			library: libraryType ? { type: libraryType } : {},
			multiple: false,
		});

		frame.on('select', function () {
			var attachment = frame.state().get('selection').first().toJSON();
			$input.val(attachment.id);
			if (type === 'image') {
				var url =
					attachment.sizes && attachment.sizes.thumbnail
						? attachment.sizes.thumbnail.url
						: attachment.url;
				$preview.html('<img class="cf-media-preview__img" src="' + url + '" alt="" />');
			} else {
				$preview.html('<span class="cf-media-preview__file">' + attachment.filename + '</span>');
			}
			$clear.prop('hidden', false);
		});

		frame.open();
	}

	function syncGalleryInput($gallery) {
		var ids = [];
		$gallery.find('.cf-gallery-preview__item').each(function () {
			var id = $(this).data('id');
			if (id) {
				ids.push(String(id));
			}
		});
		$gallery.find('.cf-gallery__input').val(ids.join(','));
		$gallery.find('.cf-gallery__clear').prop('hidden', ids.length === 0);
	}

	function openGalleryFrame($gallery) {
		var $preview = $gallery.find('.cf-gallery__preview');
		var frame = wp.media({
			title: 'Select Images',
			library: { type: 'image' },
			multiple: true,
		});

		frame.on('select', function () {
			frame.state().get('selection').each(function (attachment) {
				var data = attachment.toJSON();
				var id = data.id;
				if ($preview.find('[data-id="' + id + '"]').length) {
					return;
				}
				var url =
					data.sizes && data.sizes.thumbnail ? data.sizes.thumbnail.url : data.url;
				$preview.append(
					'<span class="cf-gallery-preview__item" data-id="' +
						id +
						'"><img class="cf-gallery-preview__img" src="' +
						url +
						'" alt="" /><button type="button" class="cf-gallery-preview__remove" aria-label="Remove">&times;</button></span>'
				);
			});
			syncGalleryInput($gallery);
		});

		frame.open();
	}

	function fetchOembed($input) {
		var url = $.trim($input.val());
		var $preview = $input.closest('.cf-field').find('.cf-oembed-preview');
		if (!url || !cfg.oembedUrl) {
			$preview.empty();
			return;
		}

		$preview.addClass('is-loading').empty().append(
			$('<span class="cf-oembed-preview__loading"></span>').text('Loading preview…')
		);

		$.get(cfg.oembedUrl, { url: url, maxwidth: 640 })
			.done(function (response) {
				if (response && response.html) {
					$preview.removeClass('is-loading').html(response.html);
				} else {
					$preview.removeClass('is-loading').empty();
				}
			})
			.fail(function () {
				$preview.removeClass('is-loading').empty();
			});
	}

	function rebuildSelectOptions($select, results, multiple, placeholder) {
		var selected = multiple
			? $select.val() || []
			: [String($select.val() || '')];
		if (!Array.isArray(selected)) {
			selected = [String(selected)];
		}

		$select.empty();
		if (!multiple) {
			$select.append($('<option>').val('').text(placeholder || '—'));
		}

		(results || []).forEach(function (item) {
			var $option = $('<option>').val(item.value).text(item.label);
			if (selected.indexOf(String(item.value)) !== -1) {
				$option.prop('selected', true);
			}
			$select.append($option);
		});
	}

	function searchRelational($wrap, query) {
		if (!cfg.searchUrl || !cfg.restNonce) {
			return;
		}

		var type = $wrap.data('cf-type');
		var $select = $wrap.find('.cf-relational__select');
		var multiple = $select.prop('multiple');
		var include = String($wrap.data('cfInclude') || '');
		var endpoint = '';
		var params = { s: query, include: include };

		if (type === 'post_object') {
			endpoint = 'posts';
			params.post_types = String($wrap.data('cfPostTypes') || '');
		} else if (type === 'term') {
			endpoint = 'terms';
			params.taxonomy = String($wrap.data('cfTaxonomy') || '');
		} else if (type === 'user') {
			endpoint = 'users';
		} else {
			return;
		}

		$wrap.addClass('is-loading');

		$.ajax({
			url: cfg.searchUrl + endpoint,
			data: params,
			beforeSend: function (xhr) {
				xhr.setRequestHeader('X-WP-Nonce', cfg.restNonce);
			},
		})
			.done(function (response) {
				rebuildSelectOptions($select, response.results || [], multiple);
			})
			.always(function () {
				$wrap.removeClass('is-loading');
			});
	}

	var searchTimers = {};

	function initRelationalSearch($wrap) {
		var $input = $wrap.find('.cf-relational-search__input');
		if (!$input.length) {
			return;
		}

		var key = $wrap.data('cf-type') + '-' + ($wrap.data('cfTaxonomy') || '') + '-' + $wrap.index();
		$input.on('input', function () {
			clearTimeout(searchTimers[key]);
			var query = $.trim($input.val());
			searchTimers[key] = setTimeout(function () {
				searchRelational($wrap, query);
			}, 300);
		});
	}

	$(function () {
		initColorPickers(document);
		$('.cf-relational-search').each(function () {
			initRelationalSearch($(this));
		});

		if ($.fn.sortable) {
			$('.cf-gallery__preview').sortable({
				items: '.cf-gallery-preview__item',
				cursor: 'move',
				tolerance: 'pointer',
				update: function () {
					syncGalleryInput($(this).closest('.cf-gallery'));
				},
			});
		}

		$(document).on('click', '.cf-media__select', function (e) {
			e.preventDefault();
			openMediaFrame($(this).closest('.cf-media'));
		});

		$(document).on('click', '.cf-media__clear', function (e) {
			e.preventDefault();
			var $wrap = $(this).closest('.cf-media');
			$wrap.find('.cf-media__input').val('');
			$wrap.find('.cf-media__preview').empty();
			$(this).prop('hidden', true);
		});

		$(document).on('click', '.cf-gallery__add', function (e) {
			e.preventDefault();
			openGalleryFrame($(this).closest('.cf-gallery'));
		});

		$(document).on('click', '.cf-gallery__clear', function (e) {
			e.preventDefault();
			var $gallery = $(this).closest('.cf-gallery');
			$gallery.find('.cf-gallery__preview').empty();
			syncGalleryInput($gallery);
		});

		$(document).on('click', '.cf-gallery-preview__remove', function (e) {
			e.preventDefault();
			var $gallery = $(this).closest('.cf-gallery');
			$(this).closest('.cf-gallery-preview__item').remove();
			syncGalleryInput($gallery);
		});

		$(document).on('input change', '.cf-oembed-url', function () {
			var $input = $(this);
			clearTimeout($input.data('cfOembedTimer'));
			$input.data(
				'cfOembedTimer',
				setTimeout(function () {
					fetchOembed($input);
				}, 400)
			);
		});

		$('.cf-oembed-url').each(function () {
			if ($.trim($(this).val()) !== '') {
				fetchOembed($(this));
			}
		});

		$(document).on('input', '.cf-range-field', function () {
			var $output = $(this).siblings('.cf-range-value');
			if ($output.length) {
				$output.text($(this).val());
			}
		});
	});

	window.wppsCfInitColorPickers = initColorPickers;
})(jQuery);
