/**
 * WooCommerce Button Text Changer
 *
 * Global frontend text replacement.
 *
 * No Product ID required.
 */

(function ($) {
    'use strict';

    /**
     * Make sure plugin settings exist.
     */
    if (
        typeof window.WBTC_DATA === 'undefined'
    ) {
        return;
    }


    /**
     * Plugin settings.
     */
    const settings = window.WBTC_DATA;


    /**
     * Check whether global changes are enabled.
     */
    function isEnabled() {

        return (
            settings.enabled === 'yes'
        );
    }


    /**
     * Safely get custom text.
     */
    function getText(key) {

        if (
            ! isEnabled()
        ) {
            return '';
        }

        if (
            typeof settings[key] === 'undefined'
        ) {
            return '';
        }

        return String(
            settings[key]
        ).trim();
    }


    /**
     * Replace text while preserving child elements.
     *
     * We only replace direct text nodes so that
     * WooCommerce icons / SVG / spans are preserved.
     */
    function replaceDirectText(
        element,
        oldTexts,
        newText
    ) {

        if (
            ! element ||
            ! newText
        ) {
            return;
        }

        const walker =
            document.createTreeWalker(
                element,
                NodeFilter.SHOW_TEXT
            );

        const textNodes = [];

        let node;

        while (
            (node = walker.nextNode())
        ) {

            textNodes.push(node);
        }


        textNodes.forEach(
            function (textNode) {

                const current =
                    textNode.nodeValue.trim();

                if (
                    oldTexts.indexOf(
                        current
                    ) !== -1
                ) {

                    textNode.nodeValue =
                        textNode.nodeValue.replace(
                            current,
                            newText
                        );
                }
            }
        );
    }


    /**
     * Change View Cart buttons.
     */
    function changeViewCartButtons() {

        const newText =
            getText(
                'view_cart'
            );

        if (
            ! newText
        ) {
            return;
        }


        const selectors = [
            '.woocommerce-message a.button',
            '.woocommerce-info a.button',
            '.added_to_cart',
            '.wc-forward',
            '.widget_shopping_cart a.button',
            '.woocommerce-mini-cart__buttons a',
            'a.wc-block-components-button'
        ];


        selectors.forEach(
            function (selector) {

                document
                    .querySelectorAll(
                        selector
                    )
                    .forEach(
                        function (button) {

                            const text =
                                button
                                    .textContent
                                    .trim();

                            if (
                                text === 'View cart' ||
                                text === 'View Cart'
                            ) {

                                replaceDirectText(
                                    button,
                                    [
                                        'View cart',
                                        'View Cart'
                                    ],
                                    newText
                                );
                            }
                        }
                    );
            }
        );
    }


    /**
     * Change Proceed to Checkout buttons.
     */
    function changeCheckoutButtons() {

        const newText =
            getText(
                'checkout'
            );

        if (
            ! newText
        ) {
            return;
        }


        const selectors = [
            '.checkout-button',
            '.wc-proceed-to-checkout a',
            '.woocommerce-mini-cart__buttons .checkout',
            '.widget_shopping_cart .checkout',
            'a.wc-block-components-button[href*="checkout"]'
        ];


        selectors.forEach(
            function (selector) {

                document
                    .querySelectorAll(
                        selector
                    )
                    .forEach(
                        function (button) {

                            replaceDirectText(
                                button,
                                [
                                    'Proceed to checkout',
                                    'Proceed to Checkout',
                                    'Continue to checkout',
                                    'Continue to Checkout'
                                ],
                                newText
                            );
                        }
                    );
            }
        );
    }


    /**
     * Change Place Order buttons.
     *
     * Normally this is already handled by
     * WooCommerce PHP filter, but this also
     * handles dynamically rendered checkout.
     */
    function changePlaceOrderButtons() {

        const newText =
            getText(
                'place_order'
            );

        if (
            ! newText
        ) {
            return;
        }


        const selectors = [
            '#place_order',
            'button[name="woocommerce_checkout_place_order"]',
            '.wc-block-components-checkout-place-order-button'
        ];


        selectors.forEach(
            function (selector) {

                document
                    .querySelectorAll(
                        selector
                    )
                    .forEach(
                        function (button) {

                            replaceDirectText(
                                button,
                                [
                                    'Place order',
                                    'Place Order'
                                ],
                                newText
                            );
                        }
                    );
            }
        );
    }


    /**
     * Change Read More buttons.
     */
    function changeReadMoreButtons() {

        const newText =
            getText(
                'read_more'
            );

        if (
            ! newText
        ) {
            return;
        }


        const selectors = [
            '.woocommerce-loop-product__link',
            'a.button',
            '.product a'
        ];


        selectors.forEach(
            function (selector) {

                document
                    .querySelectorAll(
                        selector
                    )
                    .forEach(
                        function (element) {

                            const text =
                                element
                                    .textContent
                                    .trim();

                            if (
                                text === 'Read more' ||
                                text === 'Read More'
                            ) {

                                replaceDirectText(
                                    element,
                                    [
                                        'Read more',
                                        'Read More'
                                    ],
                                    newText
                                );
                            }
                        }
                    );
            }
        );
    }


    /**
     * Run all replacements.
     */
    function updateWooCommerceButtons() {

        if (
            ! isEnabled()
        ) {
            return;
        }

        changeViewCartButtons();

        changeCheckoutButtons();

        changePlaceOrderButtons();

        changeReadMoreButtons();
    }


    /**
     * Initial load.
     */
    $(document).ready(
        function () {

            updateWooCommerceButtons();

        }
    );


    /**
     * WooCommerce AJAX completed.
     */
    $(document.body).on(
        'updated_wc_div',
        function () {

            updateWooCommerceButtons();

        }
    );


    /**
     * WooCommerce cart fragments updated.
     */
    $(document.body).on(
        'wc_fragments_loaded',
        function () {

            updateWooCommerceButtons();

        }
    );


    $(document.body).on(
        'wc_fragments_refreshed',
        function () {

            updateWooCommerceButtons();

        }
    );


    /**
     * Added to cart.
     */
    $(document.body).on(
        'added_to_cart',
        function () {

            setTimeout(
                updateWooCommerceButtons,
                100
            );

        }
    );


    /**
     * Checkout updated.
     */
    $(document.body).on(
        'updated_checkout',
        function () {

            setTimeout(
                updateWooCommerceButtons,
                100
            );

        }
    );


    /**
     * MutationObserver.
     *
     * Useful for WooCommerce Blocks,
     * Elementor dynamic widgets and AJAX content.
     */
    let observerTimeout = null;


    function observeDOMChanges() {

        if (
            ! window.MutationObserver
        ) {
            return;
        }


        const observer =
            new MutationObserver(
                function () {

                    clearTimeout(
                        observerTimeout
                    );


                    observerTimeout =
                        setTimeout(
                            function () {

                                updateWooCommerceButtons();

                            },
                            150
                        );
                }
            );


        observer.observe(
            document.body,
            {
                childList: true,
                subtree: true
            }
        );
    }


    /**
     * Start observer after DOM is ready.
     */
    $(document).ready(
        function () {

            observeDOMChanges();

        }
    );


})(jQuery);