import { attributeSelector } from '../common/selector-utilities';
import { getLoadingPromise, ensureLoadingPromiseOnlyExistsOnce } from '../common/load-utilities';

const ATTRIBUTE = Object.freeze({
    CONFIG: 'data-outdooractive-api-config',
    CLIENT: 'data-outdooractive-api-config.client',
    API_KEY: 'data-outdooractive-api-config.api-key',
    LANGUAGE: 'data-outdooractive-api-config.language',
    BASE_URL: 'data-outdooractive-api-config.base-url',
});


const loadingErrorListeners = [];

/**
 * @param {object} object
 * @returns {string}
 */
function objectToQueryString(object) {
    return Object.keys(object)
        .filter(key => !!object[ key ])
        .map(key => `${key}=${encodeURIComponent(object[ key ])}`)
        .join('&');
}

/**
 * @param {HTMLElement} configuration
 * @param {string} callbackName
 * @param {string|null} build
 * @returns {string}
 */
function getApiUrl(configuration, callbackName, build = null) {
    const query = {
        proj: configuration.getAttribute(ATTRIBUTE.CLIENT),
        key: configuration.getAttribute(ATTRIBUTE.API_KEY),
        lang: configuration.getAttribute(ATTRIBUTE.LANGUAGE) || document.documentElement.lang || 'de',
        callback: callbackName,
        build: build,
        prefer_vector: 'false',
    };
    return `//www.outdooractive.com/alpportal/oa_head.js?${objectToQueryString(query)}`;
}

/**
 * @param {string|null} build
 * @returns {Promise}
 */
function loadOutdoorActive(build = null) {
    const configuration = document.querySelector(attributeSelector(ATTRIBUTE.CONFIG));
    if (!configuration) {
        console.warn('No OA tracking configuration detected!');
        return Promise.reject('No OA tracking configuration detected!');
    }

    const callbackName = `__outdoorActiveCallback__${Math.random().toString(16).substr(2)}`;
    return new Promise((resolve, reject) => {
        window[ callbackName ] = () => resolve(window.oa);

        const script = document.createElement('script');
        script.addEventListener('error', err => {
            loadingErrorListeners.forEach(cb => cb(err));
            reject(err);
        });
        script.src = getApiUrl(configuration, callbackName, build);
        document.head.appendChild(script);
    });
}

/** @returns {Promise} */
export function loadOutdoorActiveForTracking() {
    return getLoadingPromise('oa-full')
        || ensureLoadingPromiseOnlyExistsOnce('oa-tracking', () => loadOutdoorActive('mini'));
}

/** @returns {Promise} */
export function loadOutdoorActiveFull() {
    return ensureLoadingPromiseOnlyExistsOnce('oa-full', () => loadOutdoorActive());
}

/**
 * @param {Function} callback
 * @returns {void}
 */
export function onOutdoorActiveLoadingError(callback) {
    loadingErrorListeners.push(callback);
}
