/**
 * Custom Fields repeater and flexible content row UI.
 */
(function ($) {
	'use strict';

	function renumberRows($wrap, selector) {
		$wrap.find(selector).each(function (i) {
			var $row = $(this);
			$row.attr('data-row', String(i));
			var layout = String($row.attr('data-layout') || '');
			$row.find('.cf-repeater__row-num').text(String(i + 1));
			$row.find('[name]').each(function () {
				var name = $(this).attr('name');
				if (name) {
					$(this).attr(
						'name',
						name.replace(/\[\d+\]/, '[' + i + ']').replace(/\[__ROW__\]/, '[' + i + ']')
					);
				}
			});
			if (layout) {
				setFlexibleLayoutValue($row, layout);
			}
		});
		refreshRepeaterPreviews($wrap);
	}

	function setStatus($field, message) {
		$field.find('.cf-repeater__status, .cf-flexible__status').first().text(message || '');
	}

	function updateRepeaterControls($repeater) {
		var min = parseInt($repeater.data('min'), 10) || 0;
		var max = parseInt($repeater.data('max'), 10) || 0;
		var count = $repeater.find('.cf-repeater__rows > .cf-repeater__row').length;
		$repeater.find('.cf-repeater__add').prop('disabled', max > 0 && count >= max);
		$repeater.find('.cf-repeater__remove').prop('disabled', count <= min);
		updateRepeaterPagination($repeater);
	}

	function flexibleLayoutCounts($flex) {
		var counts = {};
		$flex.find('.cf-flexible__rows > .cf-flexible__row').each(function () {
			var layout = String($(this).attr('data-layout') || '');
			if (layout) {
				counts[layout] = (counts[layout] || 0) + 1;
			}
		});
		return counts;
	}

	function selectedLayoutLimit($flex, type) {
		var $option = $flex.find('.cf-flexible__layout-select option:selected');
		return parseInt($option.data(type), 10) || 0;
	}

	function updateFlexibleControls($flex) {
		var fieldMin = parseInt($flex.data('min'), 10) || 0;
		var fieldMax = parseInt($flex.data('max'), 10) || 0;
		var $rows = $flex.find('.cf-flexible__rows > .cf-flexible__row');
		var counts = flexibleLayoutCounts($flex);
		var selectedLayout = String($flex.find('.cf-flexible__layout-select').val() || '');
		var selectedMax = selectedLayoutLimit($flex, 'max');
		var selectedCount = selectedLayout ? counts[selectedLayout] || 0 : 0;
		var disableAdd = !selectedLayout || (fieldMax > 0 && $rows.length >= fieldMax) || (selectedMax > 0 && selectedCount >= selectedMax);

		$flex.find('.cf-flexible__add').prop('disabled', disableAdd);
		$flex.find('.cf-flexible__layout-button').each(function () {
			var $button = $(this);
			var layout = String($button.data('layout') || '');
			var max = parseInt($button.data('max'), 10) || 0;
			var count = counts[layout] || 0;
			$button.toggleClass('is-active', layout === selectedLayout);
			$button.prop('disabled', fieldMax > 0 && $rows.length >= fieldMax || (max > 0 && count >= max));
			$button.find('.cf-flexible__layout-button-count').text(String(count) + (max > 0 ? '/' + max : ''));
		});
		$rows.each(function () {
			var $row = $(this);
			var layout = String($row.attr('data-layout') || '');
			var $option = $flex.find('.cf-flexible__layout-select option[value="' + layout + '"]');
			var layoutMin = parseInt($option.data('min'), 10) || 0;
			var layoutCount = counts[layout] || 0;
			$row.find('.cf-flexible__remove').prop('disabled', $rows.length <= fieldMin || (layoutMin > 0 && layoutCount <= layoutMin));
		});
	}

	function updateRepeaterPagination($repeater) {
		var perPage = parseInt($repeater.data('rowsPerPage'), 10) || 0;
		var $rows = $repeater.find('.cf-repeater__rows > .cf-repeater__row');
		var count = $rows.length;
		var $pager = $repeater.find('> .cf-repeater__footer .cf-repeater__pager');
		var $status = $pager.find('.cf-repeater__page-status');

		if (perPage <= 0 || count <= perPage) {
			$pager.prop('hidden', true);
			$rows.removeClass('cf-repeater__row--paged-hidden');
			$repeater.data('cfPage', 1);
			return;
		}

		var totalPages = Math.ceil(count / perPage);
		var page = parseInt($repeater.data('cfPage'), 10) || 1;
		page = Math.max(1, Math.min(totalPages, page));
		$repeater.data('cfPage', page);

		$rows.each(function (index) {
			var visible = index >= (page - 1) * perPage && index < page * perPage;
			$(this).toggleClass('cf-repeater__row--paged-hidden', !visible);
		});

		$pager.prop('hidden', false);
		$status.text('Page ' + page + ' of ' + totalPages);
		$pager.find('.cf-repeater__page-prev').prop('disabled', page <= 1);
		$pager.find('.cf-repeater__page-next').prop('disabled', page >= totalPages);
	}

	function compactValue(value) {
		value = $.trim(String(value || '').replace(/\s+/g, ' '));
		if (value.length > 80) {
			return value.slice(0, 77) + '...';
		}
		return value;
	}

	function fieldPreviewValue($control) {
		if (!$control.length) {
			return '';
		}

		if ($control.is(':checkbox')) {
			return $control.filter(':checked').map(function () {
				return $(this).closest('label').text() || this.value;
			}).get().join(', ');
		}

		if ($control.is(':radio')) {
			var $checked = $control.filter(':checked');
			return $checked.length ? ($checked.closest('label').text() || $checked.val()) : '';
		}

		if ($control.is('select')) {
			return $control.find('option:selected').map(function () {
				return $(this).text();
			}).get().join(', ');
		}

		return $control.first().val();
	}

	function refreshRepeaterPreview($row) {
		var collapsed = String($row.closest('.cf-repeater').data('collapsed') || '');
		var $preview = $row.find('> .cf-repeater__row-head .cf-repeater__row-preview');
		if (!$preview.length || !collapsed) {
			$preview.text('');
			return;
		}

		var suffix = '[' + collapsed + ']';
		var $control = $row.find('[name]').filter(function () {
			return String($(this).attr('name') || '').slice(-suffix.length) === suffix;
		});
		var value = compactValue(fieldPreviewValue($control));
		$preview.text(value ? ' - ' + value : '');
	}

	function refreshRepeaterPreviews($rows) {
		$rows.find('.cf-repeater__row').each(function () {
			refreshRepeaterPreview($(this));
		});
	}

	function initSortableRows($wrap, itemSelector, handleSelector) {
		if (typeof $.fn.sortable !== 'function' || $wrap.data('cfRowsSortableInit')) {
			return;
		}

		$wrap.data('cfRowsSortableInit', true);
		$wrap.sortable({
			items: '> ' + itemSelector,
			handle: handleSelector,
			cursor: 'move',
			tolerance: 'pointer',
			update: function () {
				renumberRows($wrap, itemSelector);
			},
		});
	}

	function initDynamicFieldWidgets($context) {
		if (window.wppsCfInitColorPickers) {
			window.wppsCfInitColorPickers($context);
		}
		if (window.wppsCfInitRelationalSearches) {
			window.wppsCfInitRelationalSearches($context);
		}
		if (window.wppsCfInitLayoutControls) {
			window.wppsCfInitLayoutControls($context);
		}
	}

	function setFlexibleLayoutValue($row, layout) {
		layout = String(layout || $row.attr('data-layout') || $row.find('.cf-flexible__layout-input').attr('data-layout-value') || '');
		$row.find('.cf-flexible__layout-input').each(function () {
			if (this.tagName === 'SELECT') {
				$(this).empty().append($('<option>', { value: layout, text: layout, selected: true }));
				this.value = layout;
			} else {
				this.type = 'hidden';
				this.defaultValue = layout;
				this.value = layout;
				this.setAttribute('value', layout);
			}
			this.setAttribute('data-layout-value', layout);
		});
	}

	$(function () {
		$(document).on('click', '.cf-repeater__add', function (e) {
			e.preventDefault();
			var $repeater = $(this).closest('.cf-repeater');
			var max = parseInt($repeater.data('max'), 10) || 0;
			var $rows = $repeater.find('.cf-repeater__rows');
			if (max > 0 && $rows.find('.cf-repeater__row').length >= max) {
				setStatus($repeater, 'Maximum rows reached.');
				updateRepeaterControls($repeater);
				return;
			}
			var tplEl = $repeater.find('.cf-repeater-row-template').get(0);
			var template = tplEl ? (tplEl.innerHTML || '') : '';
			if (!template) {
				return;
			}
			var index = $rows.find('.cf-repeater__row').length;
			$rows.append(template.replace(/__ROW__/g, String(index)));
			renumberRows($rows, '.cf-repeater__row');
			var perPage = parseInt($repeater.data('rowsPerPage'), 10) || 0;
			if (perPage > 0) {
				$repeater.data('cfPage', Math.max(1, Math.ceil($rows.find('.cf-repeater__row').length / perPage)));
			}
			if (typeof $.fn.sortable === 'function' && $rows.sortable('instance')) {
				$rows.sortable('refresh');
			}
			initDynamicFieldWidgets($rows.find('.cf-repeater__row').last());
			setStatus($repeater, '');
			updateRepeaterControls($repeater);
		});

		$(document).on('click', '.cf-repeater__remove', function (e) {
			e.preventDefault();
			var $repeater = $(this).closest('.cf-repeater');
			var min = parseInt($repeater.data('min'), 10) || 0;
			var $rows = $repeater.find('.cf-repeater__rows');
			if ($rows.find('.cf-repeater__row').length <= min) {
				setStatus($repeater, 'Minimum rows required.');
				updateRepeaterControls($repeater);
				return;
			}
			$(this).closest('.cf-repeater__row').remove();
			renumberRows($rows, '.cf-repeater__row');
			setStatus($repeater, '');
			updateRepeaterControls($repeater);
		});

		$(document).on('click', '.cf-repeater__page-prev, .cf-repeater__page-next', function (e) {
			e.preventDefault();
			var $repeater = $(this).closest('.cf-repeater');
			var page = parseInt($repeater.data('cfPage'), 10) || 1;
			$repeater.data('cfPage', page + ($(this).hasClass('cf-repeater__page-next') ? 1 : -1));
			updateRepeaterPagination($repeater);
		});

		$(document).on('click', '.cf-repeater__toggle, .cf-flexible__toggle', function (e) {
			e.preventDefault();
			var $button = $(this);
			var $row = $button.closest('.cf-repeater__row, .cf-flexible__row');
			var collapsed = !$row.hasClass('is-collapsed');
			$row.toggleClass('is-collapsed', collapsed);
			$button.attr('aria-expanded', collapsed ? 'false' : 'true');
			$button.attr('aria-label', collapsed ? 'Expand row' : 'Collapse row');
		});

		$(document).on('input change', '.cf-repeater__row [name]', function () {
			refreshRepeaterPreview($(this).closest('.cf-repeater__row'));
		});

		$(document).on('click', '.cf-flexible__add', function (e) {
			e.preventDefault();
			var $flex = $(this).closest('.cf-flexible');
			var layout = $flex.find('.cf-flexible__layout-select').val();
			if (!layout) {
				setStatus($flex, 'Choose a layout first.');
				updateFlexibleControls($flex);
				return;
			}
			updateFlexibleControls($flex);
			if ($(this).prop('disabled')) {
				setStatus($flex, 'Layout limit reached.');
				return;
			}
			var flexTpl = $flex.find('.cf-flexible-row-template[data-layout="' + layout + '"]').get(0);
			var template = flexTpl ? (flexTpl.innerHTML || '') : '';
			if (!template) {
				return;
			}
			var $rows = $flex.find('.cf-flexible__rows');
			var index = $rows.find('.cf-flexible__row').length;
			$rows.append(template.replace(/__ROW__/g, String(index)));
			var $newRow = $rows.find('.cf-flexible__row').last();
			$newRow.attr('data-layout', layout);
			setFlexibleLayoutValue($newRow, layout);
			renumberRows($rows, '.cf-flexible__row');
			if (typeof $.fn.sortable === 'function' && $rows.sortable('instance')) {
				$rows.sortable('refresh');
			}
			setFlexibleLayoutValue($newRow, layout);
			initDynamicFieldWidgets($newRow);
			setStatus($flex, '');
			updateFlexibleControls($flex);
		});

		$(document).on('click', '.cf-flexible__remove', function (e) {
			e.preventDefault();
			var $flex = $(this).closest('.cf-flexible');
			if ($(this).prop('disabled')) {
				setStatus($flex, 'Minimum layouts required.');
				updateFlexibleControls($flex);
				return;
			}
			var $rows = $flex.find('.cf-flexible__rows');
			$(this).closest('.cf-flexible__row').remove();
			renumberRows($rows, '.cf-flexible__row');
			if (typeof $.fn.sortable === 'function' && $rows.sortable('instance')) {
				$rows.sortable('refresh');
			}
			setStatus($flex, '');
			updateFlexibleControls($flex);
		});

		$(document).on('change', '.cf-flexible__layout-select', function () {
			var $flex = $(this).closest('.cf-flexible');
			setStatus($flex, '');
			updateFlexibleControls($flex);
		});

		$(document).on('click', '.cf-flexible__layout-button', function (e) {
			e.preventDefault();
			var $button = $(this);
			var $flex = $button.closest('.cf-flexible');
			if ($button.prop('disabled')) {
				setStatus($flex, 'Layout limit reached.');
				return;
			}
			$flex.find('.cf-flexible__layout-select').val(String($button.data('layout') || '')).trigger('change');
			$flex.find('.cf-flexible__add').trigger('click');
		});

		$('.cf-repeater__rows').each(function () {
			var $rows = $(this);
			renumberRows($rows, '.cf-repeater__row');
			initSortableRows($rows, '.cf-repeater__row', '.cf-repeater__drag');
			updateRepeaterControls($rows.closest('.cf-repeater'));
		});

		$('.cf-flexible__rows').each(function () {
			var $rows = $(this);
			renumberRows($rows, '.cf-flexible__row');
			initSortableRows($rows, '.cf-flexible__row', '.cf-flexible__drag');
			updateFlexibleControls($rows.closest('.cf-flexible'));
		});
	});
})(jQuery);
