"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const Configs_1 = require("../Configs");
const getComponent_1 = require("../getComponent");
const react_1 = tslib_1.__importStar(require("react"));
const Context_1 = require("../Context");
const react_native_1 = require("react-native");
const rtl_detect_1 = tslib_1.__importDefault(require("rtl-detect"));
/**
 * This is the context where BlueBase theme is stored.
 */
exports.IntlContext = react_1.createContext(undefined);
/**
 * BlueBase theme consumer.
 */
exports.IntlConsumer = exports.IntlContext.Consumer;
/**
 * 🈯️ IntlProvider
 */
class IntlProvider extends react_1.default.Component {
    constructor(props) {
        super(props);
        this.state = {
            direction: Configs_1.BlueBaseDefaultConfigs.direction,
            loading: true,
            locale: Configs_1.BlueBaseDefaultConfigs.locale,
            messages: {},
            rtl: false,
        };
        // This binding is necessary to make `this` work in the callback
        this.__ = this.__.bind(this);
    }
    async componentWillMount() {
        const BB = this.context;
        // Locale
        const locale = BB.Configs.getValue('locale');
        this.setLocale(locale, BB);
        // Subscribe to locale config updates
        this.unsubscribeLocale(BB);
        this.subscribeLocale(BB);
        // Content Direction
        this.setDirection(BB);
        this.unsubscribeDirection(BB);
        this.subscribeDirection(BB);
    }
    componentWillUnmount() {
        const BB = this.context;
        this.unsubscribeLocale(BB);
        this.unsubscribeDirection(BB);
    }
    /**
     * Sets a theme to Provider's state. If a theme key is given, it is used,
     * otherwise global theme is used.
     *
     * @param slug
     * @param BB
     */
    async setLocale(locale, BB) {
        if (this.state.loading !== true) {
            this.setState({ loading: true });
        }
        // Example: "bluebase.intl.messages.en", "bluebase.intl.messages.ur"
        const filterName = `bluebase.intl.messages.${locale}`;
        try {
            const messages = await BB.Filters.run(filterName, {});
            this.setState({ messages, loading: false, locale });
            this.setDirection(BB);
        }
        catch (error) {
            this.setState({
                error,
                loading: false,
            });
        }
    }
    /**
     * Sets a theme to Provider's state. If a theme key is given, it is used,
     * otherwise global theme is used.
     *
     * @param slug
     * @param BB
     */
    setDirection(BB) {
        const direction = BB.Configs.getValue('direction');
        // Decide if layout should be RTL or not
        let shouldBeRtl = false;
        if (direction === 'ltr') {
            shouldBeRtl = false;
        }
        else if (direction === 'rtl') {
            shouldBeRtl = true;
        }
        else if (direction === 'auto') {
            shouldBeRtl = !!rtl_detect_1.default.isRtlLang(this.state.locale);
        }
        // Everything is it should be, so do nothing
        if (shouldBeRtl === this.state.rtl && direction === this.state.direction) {
            return;
        }
        // Update layout
        react_native_1.I18nManager.forceRTL(shouldBeRtl);
        // Update state
        this.setState({ direction, rtl: shouldBeRtl });
    }
    __(message) {
        // We do this to keep a list off all messages in the app
        if (!this.state.messages[message]) {
            this.state.messages[message] = message;
        }
        return this.state.messages[message];
    }
    render() {
        const BB = this.context;
        const { direction, error, loading, locale, messages, rtl } = this.state;
        const retry = () => this.setLocale(locale, BB);
        if (error) {
            return react_1.default.createElement(getComponent_1.ErrorState, { error: error, retry: retry });
        }
        if (loading) {
            return react_1.default.createElement(getComponent_1.LoadingState, { retry: retry });
        }
        const value = {
            __: this.__,
            changeDirection: (dir) => { BB.Configs.setValue('direction', dir); },
            changeLocale: (newLocale) => { BB.Configs.setValue('locale', newLocale); },
            direction,
            locale,
            messages,
            rtl,
        };
        return (react_1.default.createElement(exports.IntlContext.Provider, { value: value, children: this.props.children }));
    }
    /**
     * Subscribe to locale config updates
     * @param BB
     */
    subscribeLocale(BB) {
        this.localeSubscriptionId = BB.Configs.subscribe('locale', (value) => {
            this.setLocale(value, BB);
        });
    }
    /**
     * Unsubscribe from locale config updates
     * @param BB
     */
    unsubscribeLocale(BB) {
        if (this.localeSubscriptionId) {
            BB.Configs.unsubscribe('locale', this.localeSubscriptionId);
            delete this.localeSubscriptionId;
        }
    }
    /**
     * Subscribe to direction config updates
     * @param BB
     */
    subscribeDirection(BB) {
        this.directionSubscriptionId = BB.Configs.subscribe('direction', () => {
            this.setDirection(BB);
        });
    }
    /**
     * Unsubscribe from direction config updates
     * @param BB
     */
    unsubscribeDirection(BB) {
        if (this.directionSubscriptionId) {
            BB.Configs.unsubscribe('direction', this.directionSubscriptionId);
            delete this.directionSubscriptionId;
        }
    }
}
IntlProvider.contextType = Context_1.BlueBaseContext;
exports.IntlProvider = IntlProvider;
