/**
 * RSM Content Widgets — RSM Media picker for Gutenberg media controls and SiteOrigin media fields.
 *
 * @package Rsmspark_Content_Widgets
 */
(function (window, document, $) {
	'use strict';

	function getConfig() {
		var top = window.top || window;
		return (
			top.rsmsparkCwMediaPickerConfig ||
			window.rsmsparkCwMediaPickerConfig ||
			{}
		);
	}

	function getRsmMediaOpenFrame() {
		var top = window.top || window;
		if (typeof top.rsmMediaOpenFrame === 'function') {
			return top.rsmMediaOpenFrame;
		}
		if (typeof window.rsmMediaOpenFrame === 'function') {
			return window.rsmMediaOpenFrame;
		}
		return null;
	}

	function shouldUseRsmMedia() {
		var cfg = getConfig();
		return !!cfg.useRsmMedia && typeof getRsmMediaOpenFrame() === 'function';
	}

	function attachmentThumbUrl(attachment) {
		if (!attachment) {
			return '';
		}
		if (attachment.sizes) {
			if (attachment.sizes.thumbnail && attachment.sizes.thumbnail.url) {
				return attachment.sizes.thumbnail.url;
			}
			if (attachment.sizes.medium && attachment.sizes.medium.url) {
				return attachment.sizes.medium.url;
			}
			if (attachment.sizes.full && attachment.sizes.full.url) {
				return attachment.sizes.full.url;
			}
		}
		return attachment.url || attachment.icon || '';
	}

	function openImagePicker(options, onSelect) {
		var cfg = getConfig();
		var mediaOpts = {
			title: options.title || cfg.i18n.selectImage || 'Select image',
			button: { text: options.buttonText || cfg.i18n.selectImage || 'Select image' },
			library: { type: options.libraryType || 'image' },
			multiple: !!options.multiple,
		};

		var openFrame = getRsmMediaOpenFrame();
		if (shouldUseRsmMedia() && openFrame) {
			openFrame(mediaOpts, function (attachments) {
				if (typeof onSelect === 'function') {
					onSelect(attachments || []);
				}
			});
			return;
		}

		var mediaWindow = window.top || window;
		if (typeof mediaWindow.wp === 'undefined' || !mediaWindow.wp.media) {
			return;
		}

		var frame = mediaWindow.wp.media(mediaOpts);
		frame.on('select', function () {
			var attachments = [];
			frame.state()
				.get('selection')
				.each(function (model) {
					attachments.push(model.toJSON());
				});
			if (typeof onSelect === 'function') {
				onSelect(attachments);
			}
		});
		frame.open();
	}

	function applyAttachmentToSoField($field, attachment) {
		if (!$field || !$field.length || !attachment) {
			return;
		}

		var $inputField = $field.find('.siteorigin-widget-input').not('.media-fallback-external');
		var title = attachment.title || attachment.filename || '';

		$field.find('.current .thumbnail').attr('title', title);
		$field.find('.current .title').html(title);
		$inputField.val(attachment.id || '');
		$inputField.trigger('change', { silent: true });

		var thumbUrl = attachmentThumbUrl(attachment);
		var $thumbnail = $field.find('.current .thumbnail');
		if (thumbUrl) {
			$thumbnail.attr('src', thumbUrl).fadeIn();
		} else if (attachment.icon) {
			$thumbnail.attr('src', attachment.icon).fadeIn();
		}

		$field.find('.media-remove-button').removeClass('remove-hide').attr('tabindex', 0);
	}

	function handleSoMediaUploadClick(event) {
		if (!shouldUseRsmMedia()) {
			return;
		}

		var target = event.target;
		if (!target || !target.closest) {
			return;
		}

		var btn = target.closest('.siteorigin-widget-field-type-media .media-upload-button');
		if (!btn) {
			return;
		}

		var field = btn.closest('.siteorigin-widget-field-type-media');
		if (!field) {
			return;
		}

		event.preventDefault();
		event.stopPropagation();
		event.stopImmediatePropagation();

		var $field = $(field);
		var $btn = $(btn);
		openImagePicker(
			{
				title: $btn.data('choose') || getConfig().i18n.selectImage || 'Select image',
				buttonText: $btn.data('update') || getConfig().i18n.setImage || 'Set image',
				libraryType: String($btn.data('library') || 'image').split(',')[0].trim(),
			},
			function (attachments) {
				if (attachments && attachments[0]) {
					applyAttachmentToSoField($field, attachments[0]);
				}
			}
		);

		return false;
	}

	function bindSoCaptureInterceptor(doc) {
		if (!doc || !doc.documentElement) {
			return;
		}

		var flag = 'rsmCwSoMediaCapture';
		if (doc.documentElement.getAttribute('data-' + flag) === '1') {
			return;
		}

		doc.documentElement.setAttribute('data-' + flag, '1');
		doc.addEventListener('click', handleSoMediaUploadClick, true);
	}

	function bindNestedIframeDocuments(rootWin, depth) {
		var win = rootWin || window;
		var level = depth || 0;
		if (!win || !win.document || level > 8) {
			return;
		}

		try {
			bindSoCaptureInterceptor(win.document);
			var iframes = win.document.querySelectorAll('iframe');
			for (var i = 0; i < iframes.length; i++) {
				try {
					var iframeWin = iframes[i].contentWindow;
					if (iframeWin && iframeWin.document) {
						bindNestedIframeDocuments(iframeWin, level + 1);
					}
				} catch (err) {
					// Cross-origin iframe; ignore.
				}
			}
		} catch (err) {
			// Ignore inaccessible documents.
		}
	}

	function bindSiteOriginMediaContexts(sourceWin) {
		bindSoCaptureInterceptor(document);
		bindNestedIframeDocuments(window);
		try {
			if (window.top && window.top !== window) {
				bindNestedIframeDocuments(window.top);
			}
		} catch (err) {
			// Cross-origin parent; ignore.
		}
		if (sourceWin && sourceWin.document) {
			try {
				bindSoCaptureInterceptor(sourceWin.document);
				bindNestedIframeDocuments(sourceWin);
			} catch (err) {
				// Ignore.
			}
		}
	}

	function initSiteOriginMediaFields() {
		if (!$) {
			return;
		}

		bindSiteOriginMediaContexts();

		window.addEventListener('message', function (event) {
			if (!event.data || event.data.action !== 'sowbBlockFormInit') {
				return;
			}
			var sourceWin = null;
			try {
				sourceWin = event.source;
			} catch (err) {
				sourceWin = null;
			}
			window.setTimeout(function () {
				bindSiteOriginMediaContexts(sourceWin);
			}, 0);
		});
	}

	window.RsmCwMediaPicker = {
		shouldUseRsmMedia: shouldUseRsmMedia,
		openImagePicker: openImagePicker,
		attachmentThumbUrl: attachmentThumbUrl,
		applyAttachmentToSoField: applyAttachmentToSoField,
		initSiteOriginMediaFields: initSiteOriginMediaFields,
	};

	if ($) {
		$(initSiteOriginMediaFields);
	}
})(window, document, window.jQuery);
