import data from './data';

/**
 * EmojiPicker — wires an emoji-picker.php shell (search box + grid + cell template) into a searchable,
 * category-grouped grid with a "Frequently used" row. Construct it on the element containing the shell;
 * call open() when the host dropdown/popover becomes visible. On a cell click it calls opts.onPick(glyph)
 * (the host inserts the glyph) and records the use server-side. Reused by the postbox now and the
 * comment/chat surfaces in later passes.
 */
peepso.class('EmojiPicker', function (name, peepso, $) {
	const { template } = peepso;
	const cfg = window.peepsoemojidata || {};
	const LANG = cfg.lang || {};
	const QUICK_MAX = 6;

	// Cell markup lives here (not in the PHP shell) so it survives the shell being injected as a string
	// into a body-mounted popover. peepso.template delimiters: {{- }} escapes.
	const CELL_TMPL =
		'<button type="button" class="ps-emoji-picker__cell" data-ps="emoji-cell" data-glyph="{{- data.glyph }}" title="{{- data.keywords }}">' +
		'<span class="ps-emoji-picker__glyph">{{- data.glyph }}</span></button>';

	const esc = text => $('<div>').text(text == null ? '' : text).html();

	return class {
		constructor($root, opts = {}) {
			this.$root = $($root);
			this.onPick = opts.onPick || function () {};
			// Fired after each render so a host (the popover) can re-anchor once content height is known.
			this.onRender = opts.onRender || function () {};

			this.$search = this.$root.find('[data-ps=emoji-search]');
			this.$list = this.$root.find('[data-ps=emoji-list]');
			this.cellTmpl = template(this.$root.find('[data-tmpl=emoji-cell]').html() || CELL_TMPL);

			this.payload = null;
			this.quick = [];
			this.requested = false;

			this.$search.on('input', () => this.onSearch());
			this.$list.on('click', '[data-ps=emoji-cell]', e => this.onCellClick(e));
		}

		/** Load the data once and focus search. Safe to call on every open. */
		open() {
			if (!this.requested) {
				this.requested = true;
				data
					.load()
					.done(payload => {
						this.payload = payload;
						this.quick = (payload.quick || []).slice(0, QUICK_MAX);
						this.render('');
					})
					.fail(() => {
						this.requested = false;
						this.$list.html(`<div class="ps-emoji-picker__empty">${esc(LANG.empty)}</div>`);
					});
			} else if (this.payload) {
				// Reopen: clear any prior search and reflect favorites added since last open.
				this.$search.val('');
				this.render('');
			}
			setTimeout(() => this.$search.trigger('focus'), 0);
		}

		onSearch() {
			if (!this.payload) return;
			this.render(this.$search.val().trim().toLowerCase());
		}

		cell(glyph, keywords) {
			return this.cellTmpl({ glyph: glyph, keywords: keywords || '' });
		}

		groupHeader(label) {
			return `<div class="ps-emoji-picker__group">${esc(label)}</div>`;
		}

		render(keyword) {
			if (!this.payload) return;
			const set = this.payload.set || [];

			// Searching: flat filtered grid, no favorites row or category headers.
			if (keyword) {
				const hits = set.filter(i => (i.keywords || '').indexOf(keyword) !== -1 || i.glyph === keyword);
				this.$list.html(
					hits.length
						? hits.map(i => this.cell(i.glyph, i.keywords)).join('')
						: `<div class="ps-emoji-picker__empty">${esc(LANG.empty)}</div>`
				);
				this.onRender();
				return;
			}

			let html = '';

			// Favorites — no backfill, so absent until the user has inserted something.
			if (this.quick.length) {
				html += this.groupHeader(LANG.favorites);
				html += this.quick.map(g => this.cell(g)).join('');
			}

			// Categories, a header inserted whenever the group changes (set is in emoji-test order).
			const labels = {};
			(this.payload.groups || []).forEach(g => {
				labels[g.key] = g.label;
			});
			let lastGroup = null;
			set.forEach(item => {
				if (item.group !== lastGroup) {
					lastGroup = item.group;
					html += this.groupHeader(labels[item.group] || item.group);
				}
				html += this.cell(item.glyph, item.keywords);
			});

			this.$list.html(html);
			this.onRender();
		}

		onCellClick(e) {
			e.preventDefault();
			e.stopPropagation();

			const glyph = String($(e.currentTarget).attr('data-glyph') || '');
			if (!glyph) return;

			this.onPick(glyph);

			// Optimistic favorites move + server bump.
			this.quick = [glyph].concat(this.quick.filter(g => g !== glyph)).slice(0, QUICK_MAX);
			data.bump(glyph);
		}
	};
});
