import jQ from 'jquery';
import Globals from '../helpers/globals';
import Settings from '../helpers/settings';
import Utils from '../helpers/utils';
import Api from '../helpers/api';
const BoostPFSInstantSearchCallback = (result) => {
InstantSearchApi.setDefaultValueForExcludedFields(result);
if (typeof InstantSearchApi.afterCall == 'function') {
InstantSearchApi.afterCall(result);
}
if (typeof InstantSearchApi.afterCallAsync == 'function') {
InstantSearchApi.afterCallAsync(result, callbackInstantSearchApi);
return;
}
callbackInstantSearchApi(result);
};
const getSuggestionData = (searchTerm, errorCount, eventType, previousTerm) => {
// Execute before get instant search data (customization use)
if (typeof InstantSearchApi.beforeCall == 'function') {
InstantSearchApi.beforeCall(searchTerm);
}
// Execute before get instant search data (customization use - call async 3rd party)
if (typeof InstantSearchApi.beforeCallAsync == 'function') {
var callInstantSearchApiWrapper = () => {
callInstantSearchApi(searchTerm, 0, eventType, previousTerm);
}
InstantSearchApi.beforeCallAsync(searchTerm, callInstantSearchApiWrapper);
return;
}
callInstantSearchApi(searchTerm, 0, eventType, previousTerm);
};
const callInstantSearchApi = (searchTerm, errorCount, eventType, previousTerm) => {
var errorCount = typeof errorCount !== 'undefined' ? errorCount : 0;
var previousTerm = typeof previousTerm !== 'undefined' ? previousTerm : '';
// Prepare request params
var params = prepareSuggestionParams(searchTerm, eventType);
if (params.q) {
searchTerm = params.q;
delete params.q;
}
if (previousTerm != '') params.prev_query = previousTerm;
var script = document.createElement("script");
script.type = 'text/javascript';
script.src = Api.getApiUrl('suggestion') + '?q=' + searchTerm + '&' + jQ.param(params);
script.async = true;
script.addEventListener('error', function (e) {
jQ(this).remove();
// Resend API 3 times when got the error
if (errorCount < 3) {
errorCount++;
callInstantSearchApi(params.q, eventType, previousTerm, errorCount);
} else {
// self.showError('Oops, we cannot fetch products at this moment. Please try again later.');
}
});
// Append the script element to the HEAD section.
document.getElementsByTagName('head')[0].appendChild(script);
script.addEventListener('load', function (e) {
jQ(this).remove();
});
}
const callbackInstantSearchApi = (result) => {
var cache = Globals.suggestionCache;
if (result.hasOwnProperty('prev_query')) {
var prevQuery = result.prev_query;
if (cache.hasOwnProperty(prevQuery)) {
var previousData = cache[prevQuery];
// Customize the suggest_query data
var fields = ['collections', 'did_you_mean', 'pages', 'suggestions', 'suggest_query'];
var k;
var fieldsLength = fields.length;
for (k = 0; k < fieldsLength; k++) {
result[fields[k]] = Utils.getValueInObjectArray(fields[k], previousData);
}
result['prev_total_product'] = Utils.getValueInObjectArray('total_product', previousData);
var productIndex = Utils.findIndexArray('products', previousData, 'key');
previousData[productIndex]['values'] = result['products'];
previousData.push({
key: 'local_cache',
values: true
});
previousData.push({
key: 'suggest_total_product',
values: result.total_product
});
Globals.suggestionCache[prevQuery] = previousData;
}
}
// Build elements
window.suggestionCallback(jQ.map(result, function (item, index) {
return {
key: index,
values: item
};
}));
}
const prepareSuggestionParams = (searchTerm, eventType) => {
var params = {};
params.shop = Globals.shopDomain;
params.t = new Date().getTime();
if (!Settings.getSettingValue('search.enableDefaultResult')) params.enable_default_result = false;
var enableFuzzy = Settings.getSettingValue('search.enableFuzzy');
if (enableFuzzy !== true) params.fuzzy = enableFuzzy;
if (Settings.getSettingValue('search.fullMinMatch')) params.full_min_match = true;
if (Settings.getSettingValue('search.reduceMinMatch') !== false) {
params.reduce_min_match = Settings.getSettingValue('search.reduceMinMatch');
}
if (Settings.getSettingValue('search.enablePlusCharacterSearch')) params.enable_plus_character_search = true;
// Get product/variant available or not
if (Settings.getSettingValue('search.productAvailable') == true) params.product_available = true;
// Limit
var blocks = Settings.getSettingValue('search.suggestionBlocks');
var k;
var blocksLength = blocks.length;
for (k = 0; k < blocksLength; k++) {
var id = blocks[k]['type'].slice(0, -1);
params[id + '_limit'] = blocks[k]['number'];
}
params['dym_limit'] = Settings.getSettingValue('search.suggestionDymLimit');
// Skip fields
var skipFields = Settings.getSettingValue('search.skipFields');
if (skipFields.length > 0) param.skipFields = skipFields;
params.callback = 'BoostPFSInstantSearchCallback';
params.event_type = eventType;
// Suggest types
var suggestionTypes = eventType == 'suggest_dym' ? ['products'] : Settings.getSettingValue('search.suggestionTypes');
params.suggest_types = suggestionTypes;
// Set locale param
params = Api.setApiLocaleParams(params);
// Override with Globals.instantSearchQueryParams
var mergedParams = Object.assign(params, Globals.instantSearchQueryParams);
return mergedParams;
};
/**
* The API exclude some product fields in the response.
* We set the default values for these field.
* @param apiResult
*/
const setDefaultValueForExcludedFields = (apiResult) => {
if (Array.isArray(apiResult.products)){
var currentDate = new Date();
var currentDateString = currentDate.toISOString();
apiResult.products.forEach((product) => {
if (!product.hasOwnProperty('variants')) {
product.variant = [];
}
if (!product.hasOwnProperty('images_info')) {
product.images_info = [];
}
if (!product.hasOwnProperty('collections')) {
product.collections = [];
}
if (!product.hasOwnProperty('tags')) {
product.tags = [];
}
if (!product.hasOwnProperty('skus')) {
product.skus = [];
}
if (!product.hasOwnProperty('options_with_values')) {
product.options_with_values = [];
}
if (!product.hasOwnProperty('barcodes')) {
product.barcodes = [];
}
if (!product.hasOwnProperty('created_at')) {
product.created_at = currentDateString;
}
if (!product.hasOwnProperty('updated_at')) {
product.updated_at = currentDateString;
}
if (!product.hasOwnProperty('published_at')) {
product.published_at = currentDateString;
}
})
}
}
const InstantSearchApi = {
BoostPFSInstantSearchCallback: BoostPFSInstantSearchCallback,
getSuggestionData: getSuggestionData,
prepareSuggestionParams: prepareSuggestionParams,
setDefaultValueForExcludedFields: setDefaultValueForExcludedFields,
callInstantSearchApi: callInstantSearchApi,
callbackInstantSearchApi: callbackInstantSearchApi,
beforeCall: null,
afterCall: null,
beforeCallAsync: null,
afterCallAsync: null
}
export default InstantSearchApi;