<?php
if (!defined('ABSPATH')) {
    die('-1');
}

// Check vc active or no active
if (class_exists("WPBakeryShortCode")) {
    // Begin Netbase Elements
    class nb_vc_wc_elements extends WPBakeryShortCode {

        // Element Init
        function __construct() {
            add_action('init', array($this, 'netbase_elements_map'));

            add_shortcode('nb_wcproducts', array($this, 'nb_wcproducts_render'));
        }

        // Element Mapping
        public function netbase_elements_map() {
            $order_way_values = array(
                '',
                __('Descending', 'nb-fw') => 'DESC',
                __('Ascending', 'nb-fw') => 'ASC',
            );
			$args = array(
				'type' => 'post',
				'child_of' => 0,
				'parent' => '',
				'orderby' => 'parent',
				'order' => 'ASC',
				'hide_empty' => false,
				'hierarchical' => 1,
				'exclude' => '',
				'include' => '',
				'number' => '',
				'taxonomy' => 'product_cat',
				'pad_counts' => false,
			);
			$categories = get_categories($args);
			$product_categories_dropdown = array();
			$this->getCategoryChildsFull(0, 0, $categories, 0, $product_categories_dropdown);

			$attributes_tax = wc_get_attribute_taxonomies();
			$attributes = array();
			foreach ($attributes_tax as $attribute) {
				$attributes[$attribute->attribute_label] = $attribute->attribute_name;
			}

			$product_views = array(
				__('Recent products', 'nb-fw') => 'recent_products',
				__('Featured products', 'nb-fw') => 'featured_products',
				__('Product Category', 'nb-fw') => 'product_cat',
				__('Sale Products', 'nb-fw') => 'sale_products',
				__('Best Selling Products', 'nb-fw') => 'best_selling_products',
				__('Top Rated Products', 'nb-fw') => 'top_rated_products',
			);
			$order_products = array(
				'',
				__('Date', 'nb-fw') => 'date',
				__('ID', 'nb-fw') => 'ID',
				__('Author', 'nb-fw') => 'author',
				__('Title', 'nb-fw') => 'title',
				__('Modified', 'nb-fw') => 'modified',
				__('Random', 'nb-fw') => 'rand',
				__('Comment count', 'nb-fw') => 'comment_count',
				__('Menu order', 'nb-fw') => 'menu_order',
			);

			vc_map(array(
				"name" => __("NB - Woocommerce Products"),
				"base" => "nb_wcproducts",
				'icon' => 'icon-wpb-woocommerce',
				"category" => __('Netbase Elements', 'nb-fw'),
				"params" => array(
					array(
						'type' => 'dropdown',
						'heading' => __('Style', 'nb-fw'),
						'param_name' => 'style',
						'value' => array(
							__('Default', 'nb-fw') => '',
							__('Product Carousel', 'nb-fw') => 'carousel',
							__('Product Masonry', 'nb-fw') => 'masonry',
						),
						'save_always' => true,
					),
					array(
						'type' => 'checkbox',
						'heading' => __('Equal height', 'nb-fw'),
						'param_name' => 'equal_height',
						'value' => array(__('Yes', 'nb-fw') => 'true'),
						'std' => 'true',
						'save_always' => true,
						'dependency' => array(
							'element' => 'style',
							'value' => array('carousel'),
						),
					),
					array(
						'type' => 'dropdown',
						'heading' => __('Show', 'nb-fw'),
						'param_name' => 'view',
						'value' => $product_views,
						'save_always' => true,
					),
					array(
						'type' => 'dropdown',
						'heading' => __('Category', 'nb-fw'),
						'value' => $product_categories_dropdown,
						'param_name' => 'category',
						'save_always' => true,
						'description' => __('Product category list', 'nb-fw'),
						'dependency' => array(
							'element' => 'view',
							'value' => array('product_cat'),
						),
					),
					array(
						'type' => 'checkbox',
						'heading' => __('Product description', 'nb-fw'),
						'param_name' => 'product_desc',
						'value' => array(__('Show', 'nb-fw') => 'true'),
						'std' => 'true',
						'save_always' => true,
					),
					array(
						'type' => 'textfield',
						'heading' => __('Description character limit of post', 'nb-fw'),
						'param_name' => 'limit',
						'value' => '15',
						'save_always' => true,
						'dependency' => array(
							'element' => 'product_desc',
							'value' => array('true'),
						),
					),
					array(
						'type' => 'textfield',
						'heading' => __('Per page', 'nb-fw'),
						'value' => 12,
						'save_always' => true,
						'param_name' => 'per_page',
						'description' => __('The "per_page" shortcode determines how many products to show on the page', 'nb-fw'),
					),
					array(
						'type' => 'dropdown',
						'heading' => __('Columns - Large desktops', 'nb-fw'),
						'value' => array(
							'1' => '1',
							'2' => '2',
							'3' => '3',
							'4' => '4',
							'5' => '5',
							'6' => '6',
						),
						'std' => '4',
						'param_name' => 'columns-xl',
						'save_always' => true,
						'edit_field_class' => 'vc_col-sm-6',
					),
					array(
						'type' => 'dropdown',
						'heading' => __('Columns - Desktops', 'nb-fw'),
						'value' => array(
							'1' => '1',
							'2' => '2',
							'3' => '3',
							'4' => '4',
							'5' => '5',
							'6' => '6',
						),
						'std' => '4',
						'param_name' => 'columns-lg',
						'save_always' => true,
						'edit_field_class' => 'vc_col-sm-6',
					),
					array(
						'type' => 'dropdown',
						'heading' => __('Columns - Tablets', 'nb-fw'),
						'value' => array(
							'1' => '1',
							'2' => '2',
							'3' => '3',
							'4' => '4',
							'5' => '5',
							'6' => '6',
						),
						'std' => '3',
						'param_name' => 'columns-md',
						'save_always' => true,
						'edit_field_class' => 'vc_col-sm-6',
					),
					array(
						'type' => 'dropdown',
						'heading' => __('Columns - Mobile Landscape', 'nb-fw'),
						'value' => array(
							'1' => '1',
							'2' => '2',
							'3' => '3',
							'4' => '4',
							'5' => '5',
							'6' => '6',
						),
						'std' => '2',
						'param_name' => 'columns-sm',
						'save_always' => true,
						'edit_field_class' => 'vc_col-sm-6',
					),
					array(
						'type' => 'textfield',
						'heading' => __('Rows', 'nb-fw'),
						'value' => 1,
						'param_name' => 'rows',
						'save_always' => true,
						'description' => __('The rows attribute controls how many rows wide the products should be before wrapping.', 'nb-fw'),
						'dependency' => array(
							'element' => 'style',
							'value' => array('carousel'),
						),
					),
					array(
						'type' => 'dropdown',
						'heading' => __('Order by', 'nb-fw'),
						'param_name' => 'orderby',
						'value' => $order_products,
						'save_always' => true,
						'description' => sprintf(__('Select how to sort retrieved products. More at %s.', 'nb-fw'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>'),
						'dependency' => array(
							'element' => 'view',
							'value_not_equal_to' => 'best_selling_products',
						),
					),
					array(
						'type' => 'dropdown',
						'heading' => __('Sort order', 'nb-fw'),
						'param_name' => 'order',
						'value' => $order_way_values,
						'save_always' => true,
						'description' => sprintf(__('Designates the ascending or descending order. More at %s.', 'nb-fw'), '<a href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters" target="_blank">WordPress codex page</a>'),
						'dependency' => array(
							'element' => 'view',
							'value_not_equal_to' => 'best_selling_products',
						),
					),
					array(
						'type' => 'textfield',
						'heading' => __('Extra class name', 'nb-fw'),
						'param_name' => 'class',
						'description' => __('Style particular content element differently - add a class name and refer to it in custom CSS.', 'nb-fw'),
						'save_always' => true,
					),
					array(
						'type' => 'dropdown',
						'heading' => __('Gap', 'nb-fw'),
						'param_name' => 'gap',
						'group' => __('Slide Options', 'nb-fw'),
						'description' => __('Select gap between slide elements.', 'nb-fw'),
						'value' => array(
							'0px' => '0',
							'1px' => '1',
							'2px' => '2',
							'3px' => '3',
							'4px' => '4',
							'5px' => '5',
							'10px' => '10',
							'15px' => '15',
							'20px' => '20',
							'25px' => '25',
							'30px' => '30',
							'35px' => '35',
						),
						'std' => '30',
						'save_always' => true,
						'dependency' => array(
							'element' => 'style',
							'value' => array('carousel'),
						),
					),
					array(
						'type' => 'checkbox',
						'heading' => __('Navigation', 'nb-fw'),
						'param_name' => 'nav',
						'group' => __('Slide Options', 'nb-fw'),
						'description' => __('Show next/prev buttons.', 'nb-fw'),
						'value' => array(__('Show', 'nb-fw') => 'true'),
						'std' => 'true',
						'save_always' => true,
						'dependency' => array(
							'element' => 'style',
							'value' => array('carousel'),
						),
					),
					array(
						'type' => 'dropdown',
						'heading' => __('Navigation Layout', 'nb-fw'),
						'param_name' => 'nav_layout',
						'group' => __('Slide Options', 'nb-fw'),
						'value' => array(
							'Style 1' => 'style1',
							'Style 2' => 'style2',
							'Style 3' => 'style3',
							'Style 4' => 'style4',
							'Style 5' => 'style5',
						),
						'std' => 'style1',
						'save_always' => true,
						'dependency' => array(
							'element' => 'nav',
							'value' => array('true'),
						),
					),
					array(
						'type' => 'checkbox',
						'heading' => __('Dots', 'nb-fw'),
						'param_name' => 'dots',
						'group' => __('Slide Options', 'nb-fw'),
						'description' => __('Show dots navigation.', 'nb-fw'),
						'value' => array(__('Show', 'nb-fw') => 'true'),
						'save_always' => true,
						'dependency' => array(
							'element' => 'style',
							'value' => array('carousel'),
						),
					),
					array(
						'type' => 'dropdown',
						'heading' => __('Navigation Layout', 'nb-fw'),
						'param_name' => 'dots_layout',
						'group' => __('Slide Options', 'nb-fw'),
						'value' => array(
							'Circle' => 'circle',
							'Square' => 'square',
							'Square 2' => 'square2',
							'Square 3' => 'square3',
							'Rounded' => 'rounded',
							'Rounded 2' => 'rounded2',
						),
						'std' => 'circle',
						'save_always' => true,
						'dependency' => array(
							'element' => 'dots',
							'value' => array('true'),
						),
					),
					array(
						'type' => 'checkbox',
						'heading' => __('Autoplay', 'nb-fw'),
						'param_name' => 'autoplay',
						'group' => __('Slide Options', 'nb-fw'),
						'description' => __('Autoplay.', 'nb-fw'),
						'save_always' => true,
						'value' => array(__('Yes', 'nb-fw') => 'true'),
						'std' => 'true',
						'dependency' => array(
							'element' => 'style',
							'value' => array('carousel'),
						),
					),
					array(
						'type' => 'textfield',
						'heading' => __('Autoplay Speed', 'nb-fw'),
						'param_name' => 'autoplayspeed',
						'group' => __('Slide Options', 'nb-fw'),
						'description' => __('autoplay speed.', 'nb-fw'),
						'value' => '5000',
						'save_always' => true,
						'dependency' => array(
							'element' => 'autoplay',
							'value' => array('true'),
						),
					),
					array(
						'type' => 'checkbox',
						'heading' => __('HoverPause', 'nb-fw'),
						'param_name' => 'hoverpause',
						'group' => __('Slide Options', 'nb-fw'),
						'description' => __('Pause on mouse hover.', 'nb-fw'),
						'value' => array(__('Yes', 'nb-fw') => 'true'),
						'save_always' => true,
						'dependency' => array(
							'element' => 'autoplay',
							'value' => array('true'),
						),
					),
					array(
						'type' => 'css_editor',
						'heading' => __('CSS box', 'nb-fw'),
						'param_name' => 'css',
						'group' => __('Design Options', 'nb-fw'),
						'save_always' => true,
					),
				)
			));
        }

        public function getCategoryChilds($parent_id, $pos, $array, $level, &$dropdown) {
            for ($i = $pos; $i < count($array); $i ++) {
                if ($array[$i]->category_parent == $parent_id) {
                    $data = array(
                        str_repeat('- ', $level) . $array[$i]->name => $array[$i]->slug,
                    );
                    $dropdown = array_merge($dropdown, $data);
                    $this->getCategoryChilds($array[$i]->term_id, $i, $array, $level + 1, $dropdown);
                }
            }
        }

        protected function getCategoryChildsFull($parent_id, $pos, $array, $level, &$dropdown) {
            for ($i = $pos; $i < count($array); $i ++) {
                if ($array[$i]->category_parent == $parent_id) {
                    $name = str_repeat('- ', $level) . $array[$i]->name;
                    $value = $array[$i]->slug;
                    $dropdown[] = array(
                        'label' => $name,
                        'value' => $value,
                    );
                    $this->getCategoryChildsFull($array[$i]->term_id, $i, $array, $level + 1, $dropdown);
                }
            }
        }

        function getCategories() {
            $terms = get_terms('category', 'orderby=name&hide_empty=0');
            if ($terms) {
                foreach ($terms as $key => $term) {
                    $dropdown[] = array(
                        'label' => $term->name,
                        'value' => $term->slug,
                    );
                }
            }
            return $dropdown;
        }

        private static function product_loopc($query_args, $atts, $loop_name, $style) {
            global $woocommerce_loop, $product_list, $product_desc, $product_desc_limit;

            $columns_xl = (isset($atts['columns-xl']) && $atts['columns-xl']) ? absint($atts['columns-xl']) : 4;
            $columns_lg = (isset($atts['columns-lg']) && $atts['columns-lg']) ? absint($atts['columns-lg']) : $columns_xl;
            $columns_md = (isset($atts['columns-md']) && $atts['columns-md']) ? absint($atts['columns-md']) : $columns_lg;
            $columns_sm = (isset($atts['columns-sm']) && $atts['columns-sm']) ? absint($atts['columns-sm']) : $columns_md;
            $rows = (isset($atts['rows']) && $atts['rows']) ? absint($atts['rows']) : 1;
            $woocommerce_loop['cols_xl'] = $columns_xl;
            $woocommerce_loop['cols_lg'] = $columns_lg;
            $woocommerce_loop['cols_md'] = $columns_md;
            $woocommerce_loop['cols_sm'] = $columns_sm;
            $woocommerce_loop['name'] = $loop_name;
            $product_desc = (isset($atts['product_desc']) && $atts['product_desc']) ? $atts['product_desc'] : '';
            $product_desc_limit = (isset($atts['limit']) && $atts['limit']) ? $atts['limit'] : '';
            $query_args = apply_filters('woocommerce_shortcode_products_query', $query_args, $atts, $loop_name);
            $transient_name = 'wc_loop' . substr(md5(json_encode($query_args) . $loop_name), 28) . WC_Cache_Helper::get_transient_version('product_query');
            $products = get_transient($transient_name);

            if (false === $products || !is_a($products, 'WP_Query')) {
                $products = new WP_Query($query_args);
                set_transient($transient_name, $products, DAY_IN_SECONDS * 30);
            }

            ob_start();

            if ($products->have_posts()) {
                if (isset($atts['nav']) && $atts['nav']):
                    vc_icon_element_fonts_enqueue('entypo');
                endif;
                $productoptions = ' data-cols-xl=' . $columns_xl
                        . ' data-cols-lg=' . $columns_lg
                        . ' data-cols-md=' . $columns_md
                        . ' data-cols-sm=' . $columns_sm
                        . ' data-byRow=' . ($rows > 1 ? '0' : '1');
                if ($atts['style'] == 'carousel'):
                    $productoptions .= ' data-slide=owl-carousel'
                            . ' data-margin=' . ($atts['gap'] ? absint($atts['gap']) : 30)
                            . ' data-nav=' . ($atts['nav'] ? $atts['nav'] : 'false')
                            . ((isset($atts['nav_layout']) && $atts['nav_layout']) ? ' data-navlayout=' . $atts['nav_layout'] : '')
                            . ' data-dots=' . ($atts['dots'] ? $atts['dots'] : 'false')
                            . ((isset($atts['dots_layout']) && $atts['dots_layout']) ? ' data-dotslayout=' . $atts['dots_layout'] : '')
                            . ' data-autoplay=' . ((isset($atts['autoplay']) && $atts['autoplay']) ? $atts['autoplay'] : 'false')
                            . ' data-autoplayspeed=' . ((isset($atts['autoplayspeed']) && $atts['autoplayspeed']) ? absint($atts['autoplayspeed']) : 'false')
                            . ' data-autoplayHoverPause=' . ((isset($atts['hoverpause']) && $atts['hoverpause']) ? $atts['hoverpause'] : 'false');
                elseif ($atts['style'] == 'masonry'):
                    $productoptions .= ' data-layout=isotope'
                            . ' data-layout_mode=mansory';
                endif;

                // Prime caches before grabbing objects.
                update_post_caches($products->posts, array('product', 'product_variation'));
                ?>

                <?php if ($atts['style'] == 'carousel'): ?>
                    <div class="nb_owl-carousel">
                    <?php endif; ?>
                    <div class="nb_wc-products<?php echo ($atts['style'] == 'carousel' ? ' owl-carousel' : ''); ?>"<?php echo esc_attr($productoptions); ?>>

                        <?php $i = 1; ?>
                        <?php
                        while ($products->have_posts()) :

                            $products->the_post();
                            echo ($i == 1 ? '<div class="products-column' . ($atts['style'] == 'masonry' ? ' nb-isotope-item isotope-item' : '') . '">' : '');
                            echo (isset($atts['equal_height']) && $atts['equal_height'] ? '<div class="equal_box">' : '');
                            wc_get_template_part('content', 'product');
                            echo (isset($atts['equal_height']) && $atts['equal_height'] ? '</div>' : '');
                            ;
                            if ($i == $rows):
                                echo '</div>';
                                $i = 1;
                            else:
                                $i++;
                            endif;
                            ?>

                        <?php endwhile; // end of the loop. ?>

                    </div>
                    <?php if ($atts['style'] == 'carousel'): ?>
                    </div>
                <?php endif; ?>

                <?php
            } else {
                do_action("woocommerce_shortcode_{$loop_name}_loop_no_results", $atts);
            }

            woocommerce_reset_loop();
            wp_reset_postdata();
            wp_reset_query();

            return '<div class="woocommerce columns-' . $columns_xl . ' nb_wcproducts_' . ($atts['style'] ? $atts['style'] : 'default') . '">' . ob_get_clean() . '</div>';
        }

        private static function _maybe_add_category_args($args, $category, $operator) {
            if (!empty($category)) {
                if (empty($args['tax_query'])) {
                    $args['tax_query'] = array();
                }
                $args['tax_query'][] = array(
                    array(
                        'taxonomy' => 'product_cat',
                        'terms' => array_map('sanitize_title', explode(',', $category)),
                        'field' => 'slug',
                        'operator' => $operator,
                    ),
                );
            }
            return $args;
        }

        // Element HTML
        public function nb_wcproducts_render($atts) {
            extract(shortcode_atts(
                            array(
                'carousel' => '',
                'style' => '',
                'view' => '',
                'equal_height' => '',
                'product_desc' => '',
                'limit' => '',
                'category' => '',
                'per_page' => '',
                'columns-xl' => '',
                'columns-lg' => '',
                'columns-md' => '',
                'columns-xs' => '',
                'rows' => '',
                'orderby' => '',
                'order' => '',
                'gap' => '',
                'nav' => '',
                'nav_layout' => '',
                'dots' => '',
                'dots_layout' => '',
                'autoplay' => '',
                'autoplayspeed' => '',
                'hoverpause' => '',
                'class' => '',
                'css' => '',
                            ), $atts, 'nb_wcproducts'
            ));
            $operator = 'IN';
            $meta_query = WC()->query->get_meta_query();
            $tax_query = WC()->query->get_tax_query();

            switch ($atts['view']) {
                case 'recent_products':
                    $query_args['ignore_sticky_posts'] = 1;
                    $query_args['orderby'] = $atts['orderby'] ? $atts['orderby'] : 'date';
                    $query_args['order'] = $atts['order'] ? $atts['order'] : 'desc';
                    break;

                case 'featured_products':
                    $query_args['ignore_sticky_posts'] = 1;
                    $query_args['orderby'] = $atts['orderby'] ? $atts['orderby'] : 'date';
                    $query_args['order'] = $atts['order'] ? $atts['order'] : 'desc';
                    $tax_query[] = array(
                        'taxonomy' => 'product_visibility',
                        'field' => 'name',
                        'terms' => 'featured',
                        'operator' => 'IN',
                    );
                    break;

                case 'product_cat':
                    if (!$atts['category']) {
                        return '';
                    }
                    $orderby = $atts['orderby'] ? $atts['orderby'] : 'menu_order title';
                    $order = $atts['order'] ? $atts['order'] : 'asc';
                    $ordering_args = WC()->query->get_catalog_ordering_args($orderby, $order);
                    $query_args['ignore_sticky_posts'] = 1;
                    $query_args['orderby'] = $ordering_args['orderby'];
                    $query_args['order'] = $ordering_args['order'];
                    if (isset($ordering_args['meta_key'])) {
                        $query_args['meta_key'] = $ordering_args['meta_key'];
                    }
                    break;

                case 'sale_products':
                    $query_args['orderby'] = $atts['orderby'] ? $atts['orderby'] : 'date';
                    $query_args['order'] = $atts['order'] ? $atts['order'] : 'desc';
                    $query_args['no_found_rows'] = 1;
                    $query_args['post__in'] = array_merge(array(0), wc_get_product_ids_on_sale());
                    break;

                case 'best_selling_products':
                    $query_args['ignore_sticky_posts'] = 1;
                    $query_args['meta_key'] = 'total_sales';
                    $query_args['orderby'] = 'meta_value_num';
                    break;

                case 'top_rated_products':
                    $query_args['ignore_sticky_posts'] = 1;
                    $query_args['orderby'] = $atts['orderby'] ? $atts['orderby'] : 'title';
                    $query_args['order'] = $atts['order'] ? $atts['order'] : 'asc';
                    break;
            }

            $query_args = array_merge($query_args, array(
                'post_type' => 'product',
                'post_status' => 'publish',
                'posts_per_page' => $atts['per_page'],
                'meta_query' => $meta_query,
                'tax_query' => $tax_query,
            ));

            if (isset($atts['category'])) {
                $query_args = self::_maybe_add_category_args($query_args, $atts['category'], $operator);
            }

            if ($atts['view'] == 'top_rated_products') {
                add_filter('posts_clauses', array('WC_Shortcodes', 'order_by_rating_post_clauses'));
            }

            $product_loop = self::product_loopc($query_args, $atts, $atts['view'], $atts['style']);

            if ($atts['view'] == 'product_cat') {
                WC()->query->remove_ordering_args();
            }

            if ($atts['view'] == 'top_rated_products') {
                remove_filter('posts_clauses', array('WC_Shortcodes', 'order_by_rating_post_clauses'));
            }

            $css_class = 'wpb_content_element nb_' . $atts['view'] . ' nb_style_' . ($atts['style'] ? $atts['style'] : 'default') . (isset($atts['equal_height']) && $atts['equal_height'] ? ' equal_heights' : '');
            $css_class = implode(' ', array($css_class, $class));
            $css_class = apply_filters(VC_SHORTCODE_CUSTOM_CSS_FILTER_TAG, $css_class . vc_shortcode_custom_css_class($css, ' '), 'nb_wcproducts', $atts);
            $css_class = trim(preg_replace('/\s+/', ' ', $css_class));
            $output = '<div class="' . esc_attr($css_class) . '" >'
                    . $product_loop
                    . '</div>';

            return $output;
        }
    }
}
