<?php

use BrizyPlaceholders\ContentPlaceholder;

class Brizy_Content_Providers_FreeProvider extends Brizy_Content_Providers_AbstractProvider {
    public function __construct() {
        $this->registerPlaceholderName( 'group', function () {
            return new Brizy_Content_Placeholders_GroupPlaceholder();
        } );
        $this->registerPlaceholderName( 'recaptcha_site_key', function () {
            return new Brizy_Content_Placeholders_RecaptchaSiteKey();
        } );
        $this->registerPlaceholderName( 'display_by_roles', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( 'Internal Display Block By User Role', $name, function ( Brizy_Content_Context $context, ContentPlaceholder $contentPlaceholder ) {

                $attrs = $contentPlaceholder->getAttributes();
                if ( ! empty( $attrs['roles'] ) ) {
                    $roles     = explode( ',', $attrs['roles'] );
                    $userRoles = (array) wp_get_current_user()->roles;
                    if ( in_array( 'logged', $roles ) && is_user_logged_in() ) {
                        $userRoles[] = 'logged';
                    }
                    if ( Brizy_Editor_User::is_user_allowed() ) {

                        if ( ! empty( $_GET['role'] ) ) {

                            if ( $_GET['role'] === 'default' ) {
                                $roles[]     = 'default';
                                $userRoles[] = 'default';
                            } else {
                                $userRoles = [];
                                if ( $_GET['role'] == 'not_logged' ) {

                                    if ( in_array( 'not_logged', $roles ) ) {
                                        $roles[]     = 'default';
                                        $userRoles[] = 'default';
                                    }
                                } else {
                                    $userRoles[] = $_GET['role'];
                                }
                            }
                        }
                    }
                    if ( in_array( 'not_logged', $roles ) ) {

                        $roles = array_diff( $roles, [ 'not_logged' ] );
                        if ( is_user_logged_in() ) {
                            if ( ! array_intersect( $roles, $userRoles ) ) {
                                return '';
                            }
                        }
                    } else {
                        if ( ! array_intersect( $roles, $userRoles ) ) {
                            return '';
                        }
                    }
                }
                $replacer = new \BrizyPlaceholders\Replacer( $context->getProvider() );

                return $replacer->replacePlaceholders( $contentPlaceholder->getContent(), $context );
            } );
        } );
        $this->registerPlaceholderName( 'brizy_dc_image_title', function ( $name ) {
            return new Brizy_Content_Placeholders_ImageTitleAttribute( 'Internal Title Attributes', $name );
        } );
        $this->registerPlaceholderName( 'brizy_dc_image_alt', function ( $name ) {
            return new Brizy_Content_Placeholders_ImageAltAttribute( __( 'Internal Alt Attributes', 'brizy' ), $name );
        } );
        $this->registerPlaceholderName( 'brizy_dc_current_page_unique_url', function ( $name ) {
            return new Brizy_Content_Placeholders_UniquePageUrl( __( 'Uniquer page url', 'brizy' ), $name );
        } );
        $this->registerPlaceholderName( 'brizy_dc_page_language', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( __( 'WP Language', 'brizy' ), $name, get_locale() );
        } );
        $this->registerPlaceholderName( 'brizy_dc_ajax_url', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( 'Ajax Url', $name, admin_url( 'admin-ajax.php' ) );
        } );
        $this->registerPlaceholderName( 'brizy_dc_permalink', function ( $name ) {
            return new Brizy_Content_Placeholders_Permalink();
        } );
        $this->registerPlaceholderName( 'editor_sidebar', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function ( $context, $contentPlaceholder ) {

                $attrs = $contentPlaceholder->getAttributes();
                $id    = isset( $attrs['sidebarId'] ) ? $attrs['sidebarId'] : null;
                if ( $id ) {
                    ob_start();
                    dynamic_sidebar( $id );

                    return ob_get_clean();
                }

                return '';
            } );
        } );
        $this->registerPlaceholderName( 'editor_navigation', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function ( $context, $contentPlaceholder ) {

                $attrs = $contentPlaceholder->getAttributes();

                return $attrs['menuId'] ? wp_nav_menu( array( 'menu' => $attrs['menuId'], 'echo' => false ) ) : '';
            } );
        } );
        $this->registerPlaceholderName( 'menu_current_item', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function ( $context, $contentPlaceholder ) {

                $attrs = $contentPlaceholder->getAttributes();
                $link  = get_permalink();
                $menu  = wp_get_nav_menu_object( $attrs['menu'] );
                if ( $menu_items = wp_get_nav_menu_items( $menu->term_id ) ) {

                    _wp_menu_item_classes_by_context( $menu_items );
                    foreach ( $menu_items as $menu_item ) {
                        if ( $menu_item->current ) {
                            return 'brz-menu__item--current';
                        }
                    }
                }

                return "";
            } );
        } );
        $this->registerPlaceholderName( 'editor_post_field', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function ( $context, $contentPlaceholder ) {

                $attrs = $contentPlaceholder->getAttributes();
                $post  = ( $context = Brizy_Content_ContextFactory::getGlobalContext() ) ? $context->getWpPost() : get_post();
                if ( ! $post || ! isset( $attrs['property'] ) ) {
                    return '';
                }

                return $this->filterData( $attrs['property'], $post );
            } );
        } );
        $this->registerPlaceholderName( 'editor_post_info', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function () {

                $post = ( $context = Brizy_Content_ContextFactory::getGlobalContext() ) ? $context->getWpPost() : get_post();
                if ( $post ) {
                    $commentsCount      = get_approved_comments( $post->ID, [ 'count' => true ] );
                    $params             = [];
                    $params['author']   = get_the_author_meta( 'display_name', $post->post_author );
                    $params['date']     = get_the_date( '', $post );
                    $params['time']     = get_the_time( '', $post );
                    $params['comments'] = sprintf( _n( '%s comment', '%s comments', $commentsCount, 'brizy' ), number_format_i18n( $commentsCount ) );

                    return Brizy_Editor_View::get( BRIZY_PLUGIN_PATH . '/public/views/post-info', $params );
                }

                return '';
            } );
        } );
        $this->registerPlaceholderName( 'editor_posts', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function ( $context, $contentPlaceholder ) {

                $atts = $contentPlaceholder->getAttributes();
                // shortcode to use in page: {{editor_posts posts_per_page="5" category="1,2" orderby="date" order="DESC" columns="1" display_date="1" display_author="1"}}
                // this array is used as default values for displayPosts
                $extra_atts = array(
                        "columns"        => 1,
                        "display_date"   => 1,
                        "display_author" => 1,
                );
                $extra_atts = array_merge( $extra_atts, $atts );
                $posts      = $this->getPosts( $atts );

                return $this->displayPosts( $posts, $extra_atts );
            } );
        } );
        $this->registerPlaceholderName( 'editor_product_page', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( __( 'Product Page', 'brizy' ), $name, function ( $context, $contentPlaceholder ) {

                $atts = $contentPlaceholder->getAttributes();
//	            if ( ! empty( $atts['id'] ) ) {
//		            $product_data = get_post( $atts['id'] );
//		            $product = ! empty( $product_data ) && in_array( $product_data->post_type, [ 'product', 'product_variation' ] ) ? wc_setup_product_data( $product_data ) : false;
//	            }
                if ( empty( $atts['itemId'] ) && current_user_can( 'manage_options' ) ) {
                    return __( 'Please set a valid product', 'brizy' );
                }
                $this->setScriptDependency( 'brizy-preview', [
                        'zoom',
                        'photoswipe',
                        'flexslider',
                        'wc-single-product'
                ] );
                // Avoid infinite loop. There's a call of the function the_content() in the woocommerce/single-product/tabs/description.php
                remove_filter( 'the_content', [ Brizy_Admin_Templates::instance(), 'filterPageContent' ], - 12000 );
                $html = do_shortcode( '[product_page id="' . $atts['itemId'] . '"]' );
                add_filter( 'the_content', [ Brizy_Admin_Templates::instance(), 'filterPageContent' ], - 12000 );

                return $html;
            } );
        } );
        $this->registerPlaceholderName( 'editor_product_products', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( 'Products Page', $name, function ( $context, $contentPlaceholder ) {

                $atts                = $contentPlaceholder->getAttributes();
                $shortcodeAttributes = [];
                if ( isset( $atts['limit'] ) ) {
                    $shortcodeAttributes[] = sprintf( "limit=\"%d\"", (int) $atts['limit'] );
                }
                if ( isset( $atts['columns'] ) ) {
                    $shortcodeAttributes[] = sprintf( "columns=\"%d\"", (int) $atts['columns'] );
                }
                if ( isset( $atts['category'] ) ) {
                    $shortcodeAttributes[] = sprintf( "category=\"%s\"", $atts['category'] );
                }
                if ( isset( $atts['orderby'] ) ) {
                    $shortcodeAttributes[] = sprintf( "orderby=\"%s\"", $atts['orderby'] );
                }
                if ( isset( $atts['order'] ) ) {
                    $shortcodeAttributes[] = sprintf( "order=\"%s\"", $atts['order'] );
                }
                $shortcodeAttributes = implode( ' ', $shortcodeAttributes );

                return do_shortcode( '[products ' . $shortcodeAttributes . ' ]' );
            } );
        } );
        $this->registerPlaceholderName( 'editor_product_default_cart', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function () {
                return do_shortcode( '[woocommerce_cart]' );
            } );
        } );
        $this->registerPlaceholderName( 'editor_product_checkout', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function () {
                return do_shortcode( '[woocommerce_checkout]' );
            } );
        } );
        $this->registerPlaceholderName( 'editor_product_my_account', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function () {
                return do_shortcode( '[woocommerce_my_account]' );
            } );
        } );
        $this->registerPlaceholderName( 'editor_product_order_tracking', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function () {
                return do_shortcode( '[woocommerce_order_tracking]' );
            } );
        } );
        static $noticeHtml = null;
        $this->registerPlaceholderName( 'editor_woo_notice', function ( $name ) use ( &$noticeHtml ) {
            return new Brizy_Content_Placeholders_Simple( __( 'WooCommerce Notices', 'brizy' ), $name, function () use ( &$noticeHtml ) {
                if ( class_exists( 'WooCommerce' ) ) {
                    if ( $noticeHtml ) {
                        return $noticeHtml;
                    }

                    return $noticeHtml = wc_print_notices( true );
                }

                return "";
            }, self::CONFIG_KEY_TEXT );
        } );
        $this->registerPlaceholderName( 'editor_nonce', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function ( Brizy_Content_Context $context, ContentPlaceholder $contentPlaceholder ) {

                $action = $contentPlaceholder->getAttribute( 'action' );
                $show   = true;
                if ( $showFor = $contentPlaceholder->getAttribute( 'showfor' ) ) {
                    $show = false;
                    if ( 'authenticated_user' == $showFor && is_user_logged_in() ) {
                        $show = true;
                    }
                }
                if ( ! $action || ! $show ) {
                    return '';
                }

                return wp_create_nonce( $action );
            } );
        } );
        $this->registerPlaceholderName( 'random_id', function ( $name ) {
            return new Brizy_Content_Placeholders_Simple( '', $name, function ( Brizy_Content_Context $context, ContentPlaceholder $contentPlaceholder ) {
                $key = $contentPlaceholder->getAttribute( 'key' );
                if ( $key ) {
                    $ids = $context->getRecursiveRandomIds() ?: [];
                    if ( isset( $ids[ $key ] ) ) {
                        return $ids[ $key ];
                    } else {
                        $ids[ $key ] = bin2hex( random_bytes( 10 ) );
                        $context->setRandomIds( $ids );

                        return $ids[ $key ];
                    }
                }

                return bin2hex( random_bytes( 10 ) );
            } );
        } );
        $this->registerPlaceholderName( 'brizy_dc_global_block', function ( $name ) {
            return new Brizy_Content_Placeholders_GlobalBlock( __( 'Brizy Global Block', 'brizy' ), $name );
        } );
        $this->registerPlaceholderName( 'globalblock_anchor', function ( $name ) {
            return new Brizy_Content_Placeholders_GlobalBlockAnchor( 'Brizy Global Block Anchor', $name );
        } );

    }

    private function filterData( $property, $post ) {
        switch ( $property ) {
            case 'post_title':
                return get_the_title( $post );
            case 'post_excerpt':
                return get_the_excerpt( $post );
            case 'post_content':
                return get_the_content( $post );
            case 'post_password':
                return '';
            default:
                return $post->{$property};
        }
    }

    /**
     * It rewrite the wodpress function wp_trim_excerpt.
     * The only thing we do is exclude the appling of the hook the_content.
     * Further information read the description of the function getValue of this class.
     *
     * @param string $text
     * @param null $post
     *
     * @return string
     */
    public static function wp_trim_excerpt( $text = '', $post = null ) {
        global $pages;
        // not sure why this is null (this happens on author pages.. maybe there are more)
        //
        if ( is_null( $pages ) ) {
            $pages = [];
        }
        $raw_excerpt = $text;
        if ( '' == $text ) {

            $post = get_post( $post );
            $text = get_the_content( '', false, $post );
            $text = strip_shortcodes( $text );
            $text = excerpt_remove_blocks( $text );
            /** This filter is documented in wp-includes/post-template.php */
            $text = apply_filters( 'the_content', $text );
            $text = str_replace( ']]>', ']]&gt;', $text );
            /**
             * Filters the number of words in an excerpt.
             *
             * @param int $number The number of words. Default 55.
             *
             * @since 2.7.0
             *
             */
            $excerpt_length = apply_filters( 'excerpt_length', 55 );
            /**
             * Filters the string in the "more" link displayed after a trimmed excerpt.
             *
             * @param string $more_string The string shown within the more link.
             *
             * @since 2.9.0
             *
             */
            $excerpt_more = apply_filters( 'excerpt_more', ' ' . '[&hellip;]' );
            $text         = wp_trim_words( $text, $excerpt_length, $excerpt_more );
        }

        /**
         * Filters the trimmed excerpt string.
         *
         * @param string $text The trimmed text.
         * @param string $raw_excerpt The text prior to trimming.
         *
         * @since 2.8.0
         *
         */
        return apply_filters( 'wp_trim_excerpt', $text, $raw_excerpt );
    }

    private function getPosts( $atts ) {
        // here are default posts arguments: https://codex.wordpress.org/Template_Tags/get_posts
        // maybe here we need to change some attributes, unset or add something before make query
        $posts = get_posts( $atts );

        return $posts;
    }

    private function displayPosts( $posts, $extra_atts ) {
        ob_start();
        $thumbnail_size = ''; // possible sizes: thumbnail, medium, medium_large, large
        if ( (int) $extra_atts['columns'] > 1 ) {
            $thumbnail_size = 'large';
        }
        foreach ( $posts as $post ) { ?>
            <article class="brz-article">
                <h2><a href="<?php echo get_permalink( $post->ID ); ?>"><?php echo get_the_title( $post ); ?></a></h2>

                <div class="brz-post-thumbnail">
                    <?php echo get_the_post_thumbnail( $post, $thumbnail_size ); ?>
                </div>

                <div class="brz-post-description">
                    <?php echo $this->getPostExcerpt( $post ); ?>
                </div>

                <?php if ( $extra_atts['display_date'] ) { ?>
                    <div class="brz-post-date">
                        <?php echo get_the_date( "", $post ); ?>
                    </div>
                <?php } ?>

                <?php if ( $extra_atts['display_author'] ) { ?>
                    <div class="brz-post-author">
                        <a rel="author" href="<?php echo get_author_posts_url( $post->post_author ); ?>"><span
                                    itemprop="name"><?php echo get_the_author_meta( 'display_name', $post->post_author ); ?></span></a>
                    </div>
                <?php } ?>
            </article>
            <?php
        }

        return ob_get_clean();
    }

    private function getPostExcerpt( $post ) {
        if ( ! empty( $post->post_excerpt ) ) {
            // if !empty excerpt
            return $post->post_excerpt;
        }
        $the_excerpt    = strip_tags( strip_shortcodes( $post->post_content ) ); // Strips tags and shortcodes
        $excerpt_length = 50; // Sets excerpt length by word count, default in WP is 55
        $words          = explode( ' ', $the_excerpt, $excerpt_length + 1 );
        if ( count( $words ) > $excerpt_length ) {
            array_pop( $words );
            $the_excerpt = implode( ' ', $words ); // put in excerpt only the number of word that is set in $excerpt_length
        }

        return $the_excerpt;
    }
}
