Source: components/instant-search/instant-search-block/instant-search-result-block.js

import jQ from "jquery";

import BaseComponent from "../../base-component";
import Class from "../../../helpers/class";
import InstantSearchResultItemPopular from "../instant-search-item/instant-search-result-item-popular";
import InstantSearchResultItemProduct from "../instant-search-item/instant-search-result-item-product";
import InstantSearchResultItemCollection from "../instant-search-item/instant-search-result-item-collection";
import InstantSearchResultItemPage from "../instant-search-item/instant-search-result-item-page";
import InstantSearchEnum from "../../../enum/instant-search-enum";
import InstantSearchResultBlockDym from "./instant-search-result-block-dym";
import Settings from "../../../helpers/settings";

/**
 * Instant search result - result block
 * @extends BaseComponent
 */
class InstantSearchResultBlock extends BaseComponent {
	/**
	 * @constructs
	 * @param {Object} data The result block data
	 * @param {String} data.type The block type
	 * @param {String} data.status The block status
	 * @param {String} data.number The max suggest items of block
	 * @param {String} data.label The block label
	 */
	constructor(data) {
		super();
		this.type = data.type;
		this.status = data.status;
		this.maxSuggesionItems = data.number;
		this.label = data.label;
		this.notFoundLabel = data.label;
		this.isShow = false;
		this.isShowDYM = false;

		// init Did you mean block for product block
		if (this.type && this.type === InstantSearchEnum.ResultType.PRODUCTS) {
			this.blockDym = new InstantSearchResultBlockDym();
		}
		this.settings = {
			suggesionMaxItems: Settings.getSettingValue('search.suggesionMaxItems')
		}
	}

	/**
	 * Initialize the instant search result block component
	 * @todo: Add the instant search result item for all result block
	 */
	init() {
		switch(this.type){
			case InstantSearchEnum.ResultType.SUGGESTIONS:
				// FIXME: We fix the max suggestion items by 10 to cover "No search result suggestion"
				this.maxSuggesionItems = this.settings.suggesionMaxItems;
				for (var i = 0; i < this.maxSuggesionItems; i++){
					this.addComponent(new InstantSearchResultItemPopular());
				}
				break;
			case InstantSearchEnum.ResultType.PRODUCTS:
				// FIXME: We fix the max suggestion items by 10 to cover "No search result suggestion"
				this.maxSuggesionItems = this.settings.suggesionMaxItems;
				for (var i = 0; i < this.maxSuggesionItems; i++){
					this.addComponent(new InstantSearchResultItemProduct());
				}
				break;
			case InstantSearchEnum.ResultType.COLLECTIONS:
				for (var i = 0; i < this.maxSuggesionItems; i++){
					this.addComponent(new InstantSearchResultItemCollection());
				}
				break;
			case InstantSearchEnum.ResultType.PAGES:
				for (var i = 0; i < this.maxSuggesionItems; i++){
					this.addComponent(new InstantSearchResultItemPage());
				}
				break;
		}
	}

	/**
	 * Get the raw HTML template of instant search result block
	 * @param {String} [tempType] The template type <br />
	 * 		- 'dym': Get raw HTML template of Did you mean block <br />
	 * 		- Default: Get raw HTML template of instant search result block
	 * @default Empty
	 */
	getTemplate(tempType) {
		switch (tempType) {
			case 'dym':
				return `
					<li class="{{class.searchSuggestionItem}} {{class.searchSuggestion}}-dym" aria-label="Did you mean">{{dymContent}}</li>
				`;
			default:
				return `
					<li class="{{class.searchSuggestionGroup}}" data-group="{{type}}" aria-label="{{label}}">
						<ul>
							<li class="{{class.searchSuggestionHeader}}-{{type}} {{class.searchSuggestionHeader}}" aria-label="{{label}}">{{label}}</li>
							{{resultItems}}
						</ul>
					</li>
				`;
		}
	}

	/**
	 * Replace the brackets in raw html template with proper values
	 * @returns {String} HTML string
	 */
	compileTemplate() {
		if ((this.status != 'active' || !this.isShow) && !this._isShowDYM()) {
			return '';
		}
		var label = this.isAllEmpty ? this.notFoundLabel : this.label;

		return this.getTemplate()
			.replace(/{{type}}/g, this.type)
			.replace(/{{label}}/g, label)
			.replace(/{{class.searchSuggestionHeader}}/g, Class.searchSuggestionHeader)
			.replace(/{{class.searchSuggestionGroup}}/g, Class.searchSuggestionGroup)
			.replace(/{{resultItems}}/g, '');
	}

	/**
	 * Render the instant search result block
	 * @returns {Object} jQuery object
	 */
	render() {
		this.$element = jQ(this.compileTemplate());
		// Add Did you mean block in product block
		if (this.type && this.type === InstantSearchEnum.ResultType.PRODUCTS) {
			this.blockDym.render();
			if (this.blockDym.$element) {
				this.$element = jQ(this.compileTemplate());
				this.$element.find('> ul').append(this.blockDym.$element);
			}
		}

		this.children.forEach((child) => {
			if (child.$element) {
				this.$element.find('> ul').append(child.$element);
			}
		});
	}

	/**
	 * Return whether or not the DYM of product block is shown
	 */
	_isShowDYM() {
		return this.isShowDYM && this.type == InstantSearchEnum.ResultType.PRODUCTS;
	}

	/**
	 * Set data for Instant search result block
	 * @param {Object} data The result data of block
	 */
	setData(data, isAllEmpty) {
		this.data = data;
		this.isAllEmpty = isAllEmpty;
		// Set block label for product, suggestion when empty result
		if (data.hasOwnProperty('notFoundLabel')) {
			this.notFoundLabel = data.notFoundLabel;
		}
		this.children.forEach((child, index) => {
			if (data && data.length > index) {
				child.setData(data[index]);
			} else {
				child.setData(null);
			}
		});
		if (this.blockDym) {
			this.blockDym.setData(this.parent.data);
			this.isShowDYM = this.blockDym.isShow;
		}
		this.isShow = data && data.length > 0;
	}
}

export default InstantSearchResultBlock;