/**
 * Copyright schukai GmbH and contributors 2022. All Rights Reserved.
 * Node module: @schukai/monster
 * This file is licensed under the AGPLv3 License.
 * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
 */

import {internalSymbol} from "../../constants.mjs";
import {extend} from "../../data/extend.mjs";
import {Formatter} from "../../text/formatter.mjs";
import {getGlobalFunction} from "../../types/global.mjs";
import {isInstance, isString} from "../../types/is.mjs";
import {validateObject, validateString} from "../../types/validate.mjs";
import {parseLocale} from "../locale.mjs";
import {Provider} from "../provider.mjs";
import {Translations} from "../translations.mjs";

export {Fetch}

/**
 * The fetch provider retrieves a JSON file from the given URL and returns a translation object.
 * 
 * @externalExample ../../example/i18n/providers/fetch.mjs
 * @license AGPLv3
 * @since 1.13.0
 * @copyright schukai GmbH
 * @memberOf Monster.I18n.Providers
 * @see {@link https://datatracker.ietf.org/doc/html/rfc3066}
 * @tutorial i18n-locale-and-formatter
 */
 class Fetch extends Provider {

    /**
     * As options the key `fetch` can be passed. This config object is passed to the fetch method as init.
     * 
     * The url may contain placeholders (language, script, region, variants, extlang, privateUse), so you can specify one url for all translations.
     * 
     * ```
     * new Fetch('https://www.example.com/assets/${language}.json')
     * ```
     * 
     * @param {string|URL} url
     * @param {Object} options see {@link Monster.I18n.Providers.Fetch#defaults}
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/fetch}
     */
    constructor(url, options) {
        super(options);

        if (isInstance(url, URL)) {
            url = url.toString();
        }

        if (options === undefined) {
            options = {};
        }

        validateString(url);

        /**
         * @property {string}
         */
        this.url = url;

        /**
         * @private
         * @property {Object} options
         */
        this[internalSymbol] = extend({}, super.defaults, this.defaults, validateObject(options));

    }

    /**
     * Defaults
     *
     * @property {Object} fetch
     * @property {String} fetch.method=GET
     * @property {String} fetch.mode=cors
     * @property {String} fetch.cache=no-cache
     * @property {String} fetch.credentials=omit
     * @property {String} fetch.redirect=follow
     * @property {String} fetch.referrerPolicy=no-referrer
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API}
     */
    get defaults() {

        return {
            fetch: {
                method: 'GET', // *GET, POST, PUT, DELETE, etc.
                mode: 'cors', // no-cors, *cors, same-origin
                cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
                credentials: 'omit', // include, *same-origin, omit
                redirect: 'follow', // manual, *follow, error
                referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
            }
        }

    }

    /**
     *
     * @param {Locale|string} locale
     * @return {Promise}
     */
    getTranslations(locale) {

        if (isString(locale)) {
            locale = parseLocale(locale);
        }

        let formatter = new Formatter(locale.getMap())

        return getGlobalFunction('fetch')(formatter.format(this.url), this.getOption('fetch', {}))
            .then((response) => response.json()).then(data => {
                return new Translations(locale).assignTranslations(data);
            });

    }


}