<?php

/**
 * The public-facing functionality of the plugin.
 *
 * @link       http://www.welaunch.io
 * @since      1.0.0
 *
 * @package    WooCommerce_Variations_Table
 * @subpackage WooCommerce_Variations_Table/public
 */

/**
 * The public-facing functionality of the plugin.
 *
 * Defines the plugin name, version, and two examples hooks for how to
 * enqueue the admin-specific stylesheet and JavaScript.
 *
 * @package    WooCommerce_Variations_Table
 * @subpackage WooCommerce_Variations_Table/public
 * @author     Daniel Barenkamp <support@welaunch.io>
 */
class WooCommerce_Variations_Table_Public {

    /**
     * The ID of this plugin.
     *
     * @since    1.0.0
     * @access   private
     * @var      string    $plugin_name    The ID of this plugin.
     */
    private $plugin_name;

    /**
     * The version of this plugin.
     *
     * @since    1.0.0
     * @access   private
     * @var      string    $version    The current version of this plugin.
     */
    private $version;

    /**
     * options of this plugin.
     *
     * @since    1.0.0
     * @access   private
     * @var      array    $options
     */
    private $options;

    /**
     * if true this product will be excluded
     *
     * @since    1.0.0
     * @access   private
     * @var      array    $options
     */
    private $exclude;

    protected $th;
    protected $columns;
    protected $td;
    protected $first;
    protected $columnCount;
    protected $tfooter;

    /**
     * Initialize the class and set its properties.
     *
     * @since    1.0.0
     * @param      string    $plugin_name       The name of the plugin.
     * @param      string    $version    The version of this plugin.
     */
    public function __construct( $plugin_name, $version ) 
    {
        $this->plugin_name = $plugin_name;
        $this->version = $version;

        $this->variationsTableMetaDataTexts = array();
    }

    /**
     * Enqueu Styles
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @return  [type]                       [description]
     */
    public function enqueue_styles() 
    {
        global $woocommerce_variations_table_options;
        $this->options = $woocommerce_variations_table_options;
        
        if (!$this->get_option('enable')) {
            return false;
        }

        if($this->get_option('performanceOnlyWooPages') && !is_product() ){
            return;
        }

        wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/woocommerce-variations-table-public.css', array(), $this->version, 'all' );
        if($this->get_option('datatablesEnable')) {
            
            wp_enqueue_style( 'jquery-datatables', plugin_dir_url( __FILE__ ) . 'css/vendor/jquery.dataTables.min.css', array(), '1.10.18', 'all' );

            if($this->get_option('datatablesResponsive')) {
                wp_enqueue_style( 'jquery-datatables-responsive', plugin_dir_url( __FILE__ ) . 'css/vendor/responsive.dataTables.min.css', array(), '2.2.5', 'all' );
            }
            
            if($this->get_option('datatablesPrint') || $this->get_option('datatablesCopyHtml5') || $this->get_option('datatablesExcelHtml5') || $this->get_option('datatablesCsvHtml5') || $this->get_option('datatablesPdfHtml5')) {
                wp_enqueue_style( 'jquery-datatables-buttons', plugin_dir_url( __FILE__ ) . 'css/vendor/buttons.dataTables.min.css', array(), '1.6.2', 'all' );
            }

            if($this->get_option('datatablesFixedHeader') || $this->get_option('datatablesFixedFooter')) {
                wp_enqueue_style( 'jquery-datatables-fixedheader', plugin_dir_url( __FILE__ ) . 'css/vendor/fixedHeader.dataTables.min.css', array(), '3.1.7', 'all' );
            }

        }       

        if($this->get_option('lightboxEnable')) {
            wp_enqueue_style( 'luminous-lightbox', plugin_dir_url( __FILE__ ) . 'css/vendor/luminous-basic.min.css', array(), '2.3.2', 'all' );
        }

        $customCSS = $this->get_option('customCSS');
        if(empty($customCSS)) {
            return false;
        }

        file_put_contents( dirname(__FILE__)  . '/css/woocommerce-variations-table-custom.css', $customCSS);

        wp_enqueue_style( $this->plugin_name.'-custom', plugin_dir_url( __FILE__ ) . 'css/woocommerce-variations-table-custom.css', array(), $this->version, 'all');

    }

    /**
     * Enque JS SCripts
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @return  [type]                       [description]
     */
    public function enqueue_scripts() 
    {
        global $woocommerce_variations_table_options;
        $this->options = $woocommerce_variations_table_options;

        if (!$this->get_option('enable')) {
            return false;
        }

        if($this->get_option('performanceOnlyWooPages') && !is_product() ){
            return;
        }

        if($this->get_option('datatablesEnable')) {
            wp_enqueue_script( 'jquery-datatables', plugin_dir_url( __FILE__ ) . 'js/vendor/jquery.dataTables.min.js', array( 'jquery' ), '1.10.18', true );

            $jss = array();
            
            if($this->get_option('datatablesResponsive')) {
                $jss['datatables-responsive'] = plugin_dir_url( __FILE__ ) . 'js/vendor/dataTables.responsive.min.js';
            }

            if($this->get_option('datatablesPrint') || $this->get_option('datatablesCopyHtml5') || $this->get_option('datatablesExcelHtml5') || $this->get_option('datatablesCsvHtml5') || $this->get_option('datatablesPdfHtml5')) {
                $jss['datatables-buttons'] = plugin_dir_url( __FILE__ ) . 'js/vendor/dataTables.buttons.min.js';
            }

            if($this->get_option('datatablesPdfHtml5')) {
                $jss['datatables-pdfmake'] = plugin_dir_url( __FILE__ ) . 'js/vendor/pdfmake.min.js';
                $jss['datatables-vfs_fonts'] = plugin_dir_url( __FILE__ ) . 'js/vendor/vfs_fonts.js';
            }

            if($this->get_option('datatablesCopyHtml5') || $this->get_option('datatablesExcelHtml5') || $this->get_option('datatablesCsvHtml5') || $this->get_option('datatablesPdfHtml5')) {
                $jss['datatables-jszip'] = plugin_dir_url( __FILE__ ) . 'js/vendor/jszip.min.js';
                $jss['datatables-html5'] = plugin_dir_url( __FILE__ ) . 'js/vendor/buttons.html5.min.js';
            }

            if($this->get_option('datatablesPrint')) {
                $jss['datatables-print'] = plugin_dir_url( __FILE__ ) . 'js/vendor/buttons.print.min.js';
            }

            if($this->get_option('datatablesFixedHeader') || $this->get_option('datatablesFixedFooter')) {
                $jss['datatables-fixedheader'] = plugin_dir_url( __FILE__ ) . 'js/vendor/dataTables.fixedHeader.min.js';
            }   

            // if($this->get_option('datatablesColumnFilterWidgets')) {
            //     $jss['datatables-column-filter-widgets'] = plugin_dir_url( __FILE__ ) . 'js/ColumnFilterWidgets.js';
            // }

            foreach ($jss as $key => $js) {
                wp_enqueue_script( $key, $js, array( 'jquery', 'jquery-datatables' ), '1.10.21', true );
            }
        }

        if($this->get_option('lightboxEnable')) {
            wp_enqueue_script( 'luminous-lightbox', plugin_dir_url( __FILE__ ) . 'js/vendor/luminous.min.js', array( 'jquery' ), '2.3.2', true );
        }
        

        wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/woocommerce-variations-table-public.js', array( 'jquery'), $this->version, true );

        $forJS = array();
        $forJS['cart_url'] = wc_get_cart_url();
        $forJS['ajax_url'] = admin_url('admin-ajax.php');
        $forJS['lightbox'] = $this->get_option('lightboxEnable');
        $forJS['show_all'] = __('Show All', 'woocommerce-variations-table');
        $forJS['searchText'] = __('Search', 'woocommerce-variations-table');
        $forJS['addedToCart'] = __('Added to Cart', 'woocommerce-variations-table');
        $forJS['addedToCart'] = __('Added All to Cart', 'woocommerce-variations-table');
        $forJS['addAllToCart'] = __('Add all To Cart', 'woocommerce-variations-table');
        $forJS['redirectToCart'] = get_option( 'woocommerce_cart_redirect_after_add');
        $forJS['performanceUseAJAX'] = $this->get_option('performanceUseAJAX');

        $numericSortingColumns = array();
        $dataToShow = $this->get_option('variationsTableData');
        if(isset($dataToShow['enabled'])) {
            $dataToShow = $dataToShow['enabled'];
            unset($dataToShow['placebo']);
            $priceColumnPosition = array_search('pr', array_keys( $dataToShow ));
            if(!empty($priceColumnPosition)) {

                if(count($this->get_option('variationsTableData')['enabled']) == $priceColumnPosition) {
                    $numericSortingColumns[] = $priceColumnPosition - 1;    
                } else {
                    $numericSortingColumns[] = $priceColumnPosition;
                }
                
            }
        }

        $forJS['numericSortingColumns'] = $numericSortingColumns;

        $forJS = apply_filters('woocommerce_variations_table_js_settings', $forJS);
        wp_localize_script($this->plugin_name, 'woocommerce_variations_table_options', $forJS);

        $customJS = $this->get_option('customJS');
        if(empty($customJS))
        {
            return false;
        }

        file_put_contents( dirname(__FILE__)  . '/js/woocommerce-variations-table-custom.js', $customJS);

        wp_enqueue_script( $this->plugin_name.'-custom', plugin_dir_url( __FILE__ ) . 'js/woocommerce-variations-table-custom.js', array( 'jquery' ), $this->version, true );
        
    }

    /**
     * Get Options
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @param   [type]                       $option [description]
     * @return  [type]                               [description]
     */
    private function get_option($option)
    {
        if(!is_array($this->options)) {
            return false;
        }
        
        if(!array_key_exists($option, $this->options))
        {
            return false;
        }
        return $this->options[$option];
    }
    
    /**
     * Inits the Variations Table
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @return  [type]                       [description]
     */
    public function init()
    {

        global $woocommerce_variations_table_options;

        if(empty($woocommerce_variations_table_options)) {
            $woocommerce_variations_table_options = get_option('woocommerce_variations_table_options');
        }

        $this->options = $woocommerce_variations_table_options;
        if (!$this->get_option('enable')) {
            return false;
        }

        $excludeUserRoles = $this->get_option('applyForExcludeUserRoles');
        if(is_array($excludeUserRoles) && !empty($excludeUserRoles)) {

            $currentUserRole = $this->get_user_role();
            if(in_array($currentUserRole, $excludeUserRoles)) {
                return false;
            }
        }

        // Only not logged in
        if($this->get_option('applyForUserGroup') == 2) {
            if(is_user_logged_in()) {
                return false;
            }
        }

        // Only logged in
        if($this->get_option('applyForUserGroup') == 3) {
            if(!is_user_logged_in()) {
                return false;
            }
        }

        if($this->get_option('hardRemove')) {
            add_action('wp_head', array($this, 'hardRemove'), 100);
        }

        add_filter( 'woocommerce_get_item_data', array($this, 'display_cart_item_custom_meta_data'), 10, 2 );
        add_action( 'woocommerce_checkout_create_order_line_item', array($this, 'save_cart_item_custom_meta_as_order_item_meta'), 10, 4 );
        // add_filter( 'woocommerce_after_order_itemmeta', array($this, 'show_custom_order_meta'), 20, 3 );

        $variationsTableMetaDataTexts = $this->get_option('variationsTableMetaDataTexts');
        if(!empty($variationsTableMetaDataTexts)) {

            $temp = array();
            foreach($variationsTableMetaDataTexts as $variationsTableMetaDataText) {
                $variationsTableMetaDataTextSplit = explode('|', $variationsTableMetaDataText);
                if(empty($variationsTableMetaDataTextSplit[0]) || empty($variationsTableMetaDataTextSplit[1])) {
                    continue;
                }
                $temp[$variationsTableMetaDataTextSplit[0]] = $variationsTableMetaDataTextSplit[1];
            }
            $this->variationsTableMetaDataTexts = $temp;
        }

        add_action( 'woocommerce_before_single_product', array($this,  'check_single' ) );
    }


    public function display_cart_item_custom_meta_data( $item_data, $cart_item ) 
    {

        if ( isset($cart_item['woocommerce_variations_table_custom_field_1']) && !empty($cart_item['woocommerce_variations_table_custom_field_1']) ) {

            $item_data[] = array(
                'key'       => $this->get_option('variationsTableCustomTextField1') . ': ',
                'value'     =>  $cart_item['woocommerce_variations_table_custom_field_1'],
            );
        }

        if ( isset($cart_item['woocommerce_variations_table_custom_field_2']) && !empty($cart_item['woocommerce_variations_table_custom_field_2']) ) {

            $item_data[] = array(
                'key'       => $this->get_option('variationsTableCustomTextField2') . ': ',
                'value'     =>  $cart_item['woocommerce_variations_table_custom_field_2'],
            );
        }

        return $item_data;
    }
        
    public function save_cart_item_custom_meta_as_order_item_meta( $item, $cart_item_key, $values, $order ) 
    {

        if ( isset($values['woocommerce_variations_table_custom_field_1']) && !empty($values['woocommerce_variations_table_custom_field_1']) ) {
            $item->update_meta_data( $this->get_option('variationsTableCustomTextField1'), $values['woocommerce_variations_table_custom_field_1'] );
        }

        if ( isset($values['woocommerce_variations_table_custom_field_2']) && !empty($values['woocommerce_variations_table_custom_field_2']) ) {
            $item->update_meta_data( $this->get_option('variationsTableCustomTextField2'), $values['woocommerce_variations_table_custom_field_2'] );
        }
    }

    /**
     * Check if apply on single Product
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @return  [type]                       [description]
     */
    public function check_single()
    {
        $apply = true;

        $excludeProductCategories = $this->get_option('excludeProductCategories');
        if(!empty($excludeProductCategories)) 
        {
            if($this->excludeProductCategories()) {
                $apply = false;
            }
        }

        $excludeProducts = $this->get_option('excludeProducts');
        if(!empty($excludeProducts)) 
        {
            if($this->excludeProducts()) {
                $apply = false;
            }
        }

        // Not in exclusion list
        if($apply) {

            $this->remove_add_to_cart();
            $variationsTablePosition = $this->get_option('variationsTablePosition');
            $variationsTablePriority = $this->get_option('variationsTablePriority');
            !empty($variationsTablePosition) ? $variationsTablePosition = $variationsTablePosition : $variationsTablePosition = 'woocommerce_after_single_product_summary';
            !empty($variationsTablePriority) ? $variationsTablePriority = $variationsTablePriority : $variationsTablePriority = 5;
            add_action( $variationsTablePosition, array($this,'variationsTable'), $variationsTablePriority );
        }
    }

    public function variations_table_shortcode($atts)
    {
        $excludeUserRoles = $this->get_option('applyForExcludeUserRoles');
        if(is_array($excludeUserRoles) && !empty($excludeUserRoles)) {

            $currentUserRole = $this->get_user_role();
            if(in_array($currentUserRole, $excludeUserRoles)) {
                return false;
            }
        }

        // Only not logged in
        if($this->get_option('applyForUserGroup') == 2) {
            if(is_user_logged_in()) {
                return false;
            }
        }

        // Only logged in
        if($this->get_option('applyForUserGroup') == 3) {
            if(!is_user_logged_in()) {
                return false;
            }
        }
        
        $args = shortcode_atts( array(
            'product' => '',
            'products' => '',
            'category' => '',
        ), $atts );

        $product_id = intval($args['product']);
        $products = !empty($args['products']) ? explode(',', $args['products']) : '';
        $category = intval($args['category']);

        $product_ids = array();
        if(!empty($category)) {
             $args = array(
                'post_type'             => 'product',
                'post_status'           => 'publish',
                'ignore_sticky_posts'   => 1,
                'posts_per_page'        => -1,
                'tax_query'             => array(
                    array(
                        'taxonomy'      => 'product_cat',
                        'field'         => 'term_id',
                        'terms'         => $category,
                        'operator'      => 'IN'
                    ),
                )
            );
            $products_query = new WP_Query($args);
            if(!empty($products_query->posts)) {
                foreach ($products_query->posts as $product_query) {
                    $product_ids[] = $product_query->ID;
                }
            }
        } elseif (!empty($products)) {
            $product_ids = $products;
        } else {
            if(empty($product_id)) {
                global $post;
                $product_ids[] = $post->ID;
            } else {
                $product_ids[] = $product_id;
            }   
        }

        if(empty($product_ids)) {
            return 'No Products found.';
        }

        ob_start();

        global $product;
        $originalProduct = $product;

        foreach ($product_ids as $product_id) {

        
            $product = wc_get_product($product_id);
            if(!$product) {
                continue;
            }

            if(!$product->is_type('variable')) {
                continue;
            }

            $this->variationsTable(true);
        }

        $this->getTable($product);
        
        $product = $originalProduct;
        
        $html = ob_get_contents();
        ob_end_clean();
        return $html;
    }

   /**
     * Creates the variations Table
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @return  [type]                       [description]
     */
    public function variationsTable($multiple = false)
    {
        global $product, $woocommerce, $woocommerce_catalog_mode_options;

        if(!$product) {
            return false;
        }

        if(!$product->is_type( 'variable' )) {
            return false;
        }

        $enabled = apply_filters('woocommerce_variations_table_enabled', true, $product );
        if(!$enabled) {
            return false;
        }

        $variationsTableTitle = apply_filters('woocommerce_variations_table_title', $this->get_option('variationsTableTitle') );
        $this->variationsTableData = apply_filters('woocommerce_variations_table_data', $this->get_option('variationsTableData') );

        $this->variationsTableData = $this->variationsTableData['enabled'];
        unset($this->variationsTableData['placebo']);

        if(!$this->variationsTableData) {
            return;
        }

        if(!empty($woocommerce_catalog_mode_options) && isset($this->variationsTableData['ca']) && $woocommerce_catalog_mode_options['removeAddToCart'] == "1" && empty($woocommerce_catalog_mode_options['enquiryCartEnable']) ) {

            $catalogModeExcludeProductCategories = $woocommerce_catalog_mode_options['excludeProductCategories'];
            $catalogModeExcludeProductCategoriesRevert = $woocommerce_catalog_mode_options['excludeProductCategoriesRevert'];

            $productCategories = $product->get_category_ids();
            if(!empty($catalogModeExcludeProductCategories)) {

                foreach ($productCategories as $productCategoryId) {
                    if($catalogModeExcludeProductCategoriesRevert == "1") {
                        if(!in_array($productCategoryId, $excludeProductCategories)) {
                            unset($this->variationsTableData['ca']);

                        }
                    } else {
                        if(in_array($productCategoryId, $excludeProductCategories)) {
                            unset($this->variationsTableData['ca']);
                        }
                    }
                }
            }

            $catalogModeExcludeProducts = $woocommerce_catalog_mode_options['excludeProducts'];
            $catalogModeExcludeProductsRevert = $woocommerce_catalog_mode_options['excludeProductsRevert'];

            if(empty($catalogModeExcludeProducts)) {
                unset($this->variationsTableData['ca']);
            } else {

                if(empty($catalogModeExcludeProductsRevert) && !in_array($product->get_id(), $catalogModeExcludeProducts)) {
                    unset($this->variationsTableData['ca']);
                } elseif($catalogModeExcludeProductsRevert == "1" && in_array($product->get_id(), $catalogModeExcludeProducts)) {
                    unset($this->variationsTableData['ca']);
                }
            }

        }

        $attributes = $product->get_attributes();
        $attribute_keys = array_keys( $attributes );
        $available_variations = $product->get_available_variations();

        if(empty($available_variations)) {
            
            if(!empty($this->get_option('emptyVariationsText'))) {
                echo do_shortcode( wpautop( $this->get_option('emptyVariationsText') ));
            }
            return;
        }

        if( version_compare( $woocommerce->version, '3.0.0', ">=" ) ) {
            $selected_attributes = $product->get_default_attributes();
        } else {
            $selected_attributes = $product->get_variation_default_attributes();
        }

        if(!isset($this->th)) {
            $this->th = '';
        }

        if(!isset($this->columns)) {
            $this->columns = array();
        }

        if(!isset($this->td)) {
            $this->td = '';
        }
        if(!isset($this->first)) {
            $this->first = true;
        }

        if($this->first && !empty($variationsTableTitle)) {
            echo '<h2>' . $variationsTableTitle . '</h2>';
        }
        if(!isset($this->columnCount)) {
            $this->columnCount = 0;
        }

        $blacklistKeys = array('im', 'qt','ca','mc','mq','wi','pd','eq');

        foreach ($available_variations as $variation) {

            $variation_product = new WC_Product_Variation( $variation['variation_id'] );
            if(!$variation_product) {
                continue;
            }

            // $visible = apply_filters( 'woocommerce_variation_is_visible', $variation['variation_id'], $product, $variation_product);
            $visible = apply_filters( 'woocommerce_variation_is_visible', 'publish' === get_post_status( $variation_product->get_id() ) && '' !== $variation_product->get_price(), $variation_product->get_id(), $variation_product->get_parent_id(), $variation_product );
            if(!$visible) {
                continue;
            }

            if($this->get_option('hideOutOfStockVariations') && ( $variation_product->get_stock_quantity() < 1 || $variation_product->get_stock_status() == "outofstock") ) {
                continue;
            }

            $this->td .= '<tr id="variations-table-row-' . $variation_product->get_id() . '" class="variations-table-row">';
            foreach($this->variationsTableData as $variationsTableDataKey => $variationsTableDataValue) {

                if($variationsTableDataKey == "at") {

                    foreach ($variation_product->get_attributes() as $attr_name => $attr_value) {

                        if(isset($attributes[$attr_name]) && is_object($attributes[$attr_name])) {

                            if(is_array($attributes[$attr_name]['data'])) {
                                if(!$attributes[$attr_name]['data']['visible']) {
                                    continue;
                                }
                            }
                        }

                        $attr_name = urldecode($attr_name);
                        $attr_value = urldecode($attr_value);
                        $original_attr_value = $attr_value;

                        $preselect = '';

                        // Get the correct variation values
                        if (strpos($attr_name, 'pa_') !== FALSE){ // variation is a pre-definted attribute
                            // $attr_name = substr($attr_name, 3);
                            $attr = get_term_by('slug', $attr_value, $attr_name);

                            // any attributes
                            if(!$attr) {
                                // continue;
                            }

                            if($attr) {
                                if(!empty($selected_attributes)) {
                                    if(isset($selected_attributes[$attr_name]) && $selected_attributes[$attr_name] == $attr_value){
                                        $preselect = 'data-preselect="' . apply_filters('woocommerce_attribute_value_image', esc_html( $attr->name ), $attr->term_id) . '"';
                                    }
                                }

                                $attr_value = apply_filters('woocommerce_attribute_value_image', esc_html( $attr->name ), $attr->term_id);
                                if(empty($attr_value) && isset($attr->name)) {
                                    $attr_value = $attr->name;
                                }
                            }
                            
                            $attr_label = wc_attribute_label($attr_name);

                        } else {
                            $attr = maybe_unserialize( get_post_meta( $product->get_id(), '_product_attributes' ) );
                            $attr_label = wc_attribute_label( $attr[0][$attr_name]['name'] );
                        }

                        if($this->first) {

                            $this->th .= '<th id="variations-table-header-' . $variationsTableDataKey . '-' . $attr_label .'" ' . $preselect . ' class="variations-table-header variations-table-header-' . $variationsTableDataKey . '">' . $attr_label . '</th>';
                            $this->columnCount++;

                            $this->columns[] = array(
                                'data' => $attr_name,
                                'name' => $attr_label,
                                'title' => $attr_label,
                            );
                        }

                        $orderValue = $original_attr_value;
                        if (preg_match('~[0-9]+~', $orderValue)) {
                            $orderValue = floatval($orderValue);
                        }

                        $this->td .= '<td data-order="' . $orderValue . '" data-th="' . $attr_name . '" class="variations-table-value-' . $variationsTableDataKey . ' variations-table-value">';

                        if(!$this->get_option('datatablesResponsive') && !in_array($variationsTableDataKey, $blacklistKeys)) {
                            $this->td .= '<span class="variations-table-only-mobile">' . $attr_label . ': </span>';
                        }
                        
                        $this->td .= $attr_value . '</td>';
                    }
                    continue;
                }

                $variationsTableDataDataValue = $this->getVariationData($variationsTableDataKey, $variation_product);

                if($this->first) {

                    if($variationsTableDataKey == "mc") {
                        $variationsTableDataValue = "";
                    } elseif($variationsTableDataKey == "mq") {
                        $variationsTableDataValue = __('Quantity', 'woocommerce-variations-table');
                    } elseif($variationsTableDataKey == "c1") {
                        $variationsTableDataValue = $this->get_option('variationsTableCustomTextField1');
                    } elseif($variationsTableDataKey == "c2") {
                        $variationsTableDataValue = $this->get_option('variationsTableCustomTextField2');
                    } elseif (strpos($variationsTableDataKey, 'meta_') !== FALSE){ // variation is a pre-definted attribute
                        $meta_key = substr($variationsTableDataKey, 5);
                        if(isset($this->variationsTableMetaDataTexts[$meta_key]) && !empty($this->variationsTableMetaDataTexts[$meta_key])) {
                            $variationsTableDataValue = $this->variationsTableMetaDataTexts[$meta_key];
                        }
                    }    

                    if($this->get_option('priceQuantityTextsPerCategory')) {
                        $priceQuantityTextsPerCategoryCategories = $this->get_option('priceQuantityTextsPerCategoryCategories');
                        if(!empty($priceQuantityTextsPerCategoryCategories)) {

                            $productCategories = get_the_terms($product->get_id(), 'product_cat');
                            $productCategoryIds = array_column($productCategories, 'term_id');

                            $priceQuantityTextsPerCategoryTest = array_intersect($productCategoryIds, $priceQuantityTextsPerCategoryCategories);
                            if(!empty($priceQuantityTextsPerCategoryTest)) {
                                if($variationsTableDataKey == "mq" || $variationsTableDataKey == "qt") {
                                    $variationsTableDataValue = $this->get_option('priceQuantityTextsPerCategoryQuantityText');
                                } elseif($variationsTableDataKey == "pr") {
                                    $variationsTableDataValue = $this->get_option('priceQuantityTextsPerCategoryPriceText');
                                }            
                            }                
                        }
                    }

                    $this->th .= '<th id="variations-table-header-' . $variationsTableDataKey . '" class="variations-table-header">' . __( $variationsTableDataValue, 'woocommerce-variations-table' ) . '</th>';

                    $this->columns[] = array(
                        'data' => $variationsTableDataKey,
                        'name' => __( $variationsTableDataValue, 'woocommerce-variations-table' ),
                        'title' => __( $variationsTableDataValue, 'woocommerce-variations-table' ),
                    );

                    $this->columnCount++;
                }

                // data-order="' . (float) filter_var( str_replace(' - ', '', strip_tags($variationsTableDataDataValue) ), FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION ) . '"
                $this->td .=  '<td data-th="' . __( $variationsTableDataValue, 'woocommerce-variations-table' ) . '" class="variations-table-value-' . $variationsTableDataKey . ' variations-table-value">';

                if(!$this->get_option('datatablesResponsive') && !in_array($variationsTableDataKey, $blacklistKeys)) {
                    $this->td .=  '<span class="variations-table-only-mobile">' . __( $variationsTableDataValue, 'woocommerce-variations-table' ) . ': </span>';
                }

                $this->td .= $variationsTableDataDataValue . '</td>';
            }
            $this->td .= '</tr>';
            
            $this->first = false;

            if($this->get_option('performanceUseAJAX')) {
                break;
            }
        }

        if(!$multiple) {
            $this->getTable($product);
        }
    }

    public function getTable($product)
    {
        if(empty($this->variationsTableData)) {
            return;
        }

        $this->tfooter = "";
        if(array_key_exists('mc', $this->variationsTableData) || array_key_exists('mq', $this->variationsTableData)) {

            $this->tfooter .= '<tfoot>';
                $this->tfooter .= '<tr id="variations-table-multiple-add-to-cart" class="variations-table-multiple-add-to-cart">';
                    $this->tfooter .= '<td colspan="' . $this->columnCount . '">';
                        $this->tfooter .= '<button type="button" disabled="true" href="#" id="variations-table-multiple-add-to-cart-btn" class="variations-table-multiple-add-to-cart-btn btn button btn-primary btn-lg">' . __('Add all To Cart', 'woocommerce-variations-table') . '</button>';
                    $this->tfooter .= '</td>';
                $this->tfooter .= '</tr>';
            $this->tfooter .= '</tfoot>';
        }

        do_action('woocommerce_variations_table_before_table');

        $datatablesEnabled = apply_filters('woocommerce_variations_table_datatables_enabled', $this->get_option('datatablesEnable'));

        if($datatablesEnabled == "1") {

            $this->options['datatablesColumnSearchOriginal'] = $this->options['datatablesColumnSearch'];
            if($this->get_option('datatablesFiltering')) {
                $this->options['datatablesColumnSearch'] = "1";
            }

            $datatablesOptions = array(
                'paging' => $this->get_option('datatablesPaging') == "1" ? true : false,
                'pageLength' => (int) $this->get_option('datatablesPageLength') ? (int) $this->get_option('datatablesPageLength') : 10,
                'lengthMenu' => $this->get_option('datatablesPageLengthMenu') ? explode(',', $this->get_option('datatablesPageLengthMenu') ) : array( 10, 25, 50, 60, 75, 100 ),
                'orderColumn' => !empty($this->get_option('datatablesOrderColumn')) ? $this->get_option('datatablesOrderColumn') : '',
                'orderColumnType' => !empty($this->get_option('datatablesOrderColumnType')) ? $this->get_option('datatablesOrderColumnType') : '',
                'ordering' => $this->get_option('datatablesOrdering') == "1" ? true : false,
                'info' => $this->get_option('datatablesInfo') == "1" ? true : false,
                'stateSave' => $this->get_option('datatablesStateSave') == "1" ? true : false,
                'searching' => $this->get_option('datatablesSearching') == "1" ? true : false,
                'fixedHeaderA' => $this->get_option('datatablesFixedHeader'),
                'fixedHeaderOffset' => $this->get_option('datatablesFixedHeaderOffset'),
                'fixedFooterA' => $this->get_option('datatablesFixedFooter'),
                'fixedFooterOffset' => $this->get_option('datatablesFixedFooterOffset'),
                'responsive' => $this->get_option('datatablesResponsive') == "1" ? true : false,
                'filtering' => $this->get_option('datatablesFiltering'),
                'columnSearchOriginal' => $this->get_option('datatablesColumnSearchOriginal'),
                'columnSearch' => $this->get_option('datatablesColumnSearch'),
                'orderCellsTop' => $this->get_option('datatablesColumnSearch') == "1" ? true : false,
                'columnFilterWidgets' => false,
                'sDom' => $this->get_option('datatablesSDom'),
                'language' => array(
                    'url' => '//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/' . $this->get_option('datatablesLanguage') . '.json',
                    // 'url' => '//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/German.json',
                    // 'url' => '//cdn.datatables.net/plug-ins/1.10.16/i18n/' . $this->get_option('datatablesLanguage') . '.json',
                )
            );

            if($this->get_option('datatablesScrollCollapse') == "1") {
                $datatablesOptions['scrollCollapse'] = true;
                $datatablesOptions['scrollY'] = $this->get_option('datatablesScrollY') . 'px';
            }

            $buttons = array();
            if($this->get_option('datatablesPrint') == "1") {
                $buttons[] = array(
                    'extend' => 'print',
                    'exportOptions' => array(
                        'stripHtml' => false,
                    ),
                    'text' => __('Print', 'woocommerce-variations-table'),
                );
            }
            if($this->get_option('datatablesCopyHtml5') == "1") {
                $buttons[] = array(
                    'extend' => 'copyHtml5',
                    'exportOptions' => array(
                        'stripHtml' => false,
                    ),
                    'text' => __('Copy', 'woocommerce-variations-table'),
                );
            }
            if($this->get_option('datatablesExcelHtml5') == "1") {
                $buttons[] = array(
                    'extend' => 'excelHtml5',
                    'exportOptions' => array(
                        'stripHtml' => true,
                    ),
                    'text' => __('Excel', 'woocommerce-variations-table'),
                );
            }
            if($this->get_option('datatablesCsvHtml5') == "1") {
                $buttons[] = array(
                    'extend' => 'csvHtml5',
                    'exportOptions' => array(
                        'stripHtml' => true,
                    )
                );
            }
            if($this->get_option('datatablesPdfHtml5') == "1") {
                $buttons[] = array(
                    'extend' => 'pdfHtml5',
                    'exportOptions' => array(
                        'stripHtml' => true,
                    ),
                    'text' => __('PDF', 'woocommerce-variations-table'),
                );
            }

            if(!empty($buttons)) {
                $datatablesOptions['buttons'] = $buttons;
            }

            $datatablesOptions = htmlspecialchars( json_encode( apply_filters('woocommerce_variations_table_datatables_options', $datatablesOptions) ), ENT_QUOTES, 'UTF-8');

            $columns = "";
            if($this->get_option('performanceUseAJAX')) {
                $columns = htmlspecialchars( json_encode( $this->columns), ENT_QUOTES, 'UTF-8');
            }

            echo '<table class="woocommerce-variations-table datatables nowrap" data-options="' . $datatablesOptions . '" data-product-id="' . $product->get_id() . '"  data-ajax-columns="' . $columns . '" width="100%">';
        } else {
            echo '<table class="woocommerce-variations-table nowrap rwd-table" data-product-id="' . $product->get_id() . '" width="100%">';
        }
        ?>
            <thead>
                <tr>
                    <?php echo $this->th ?>
                </tr>
            </thead>
            <tbody>
                <?php echo $this->td ?>
            </tbody>
            <?php echo $this->tfooter ?>
        </table>

        <?php
        $this->th = "";
        $this->td = "";
        $this->tfooter = "";
        unset($this->first);
        unset($this->columnCount);

        do_action('woocommerce_variations_table_after_table');
    }

    /**
     * Get Variation data by Key
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @param   [type]                       $key       [description]
     * @param   [type]                       $variation [description]
     * @return  [type]                                  [description]
     */
    public function getVariationData($key, $variation)
    {
        if(empty($key)) {
            return;
        }
        
        $html = "";

        if (strpos($key, 'meta_') !== FALSE){

            $meta_key = substr($key, 5);

            $html = get_post_meta($variation->get_id(), $meta_key, true);
            if(empty($html)) {
                $html = get_post_meta($variation->get_parent_id(), $meta_key, true);
            }
        } else {
            switch ($key) {
                case 'im':
                    $imageId = $variation->get_image_id();
                    $image = wp_get_attachment_image($imageId);
                    if(empty($imageId) || empty($image)) {
                        return wc_placeholder_img();
                    }

                    if($this->get_option('lightboxEnable')) {
                        $fullImage = wp_get_attachment_image_src($imageId, 'full');

                        $html = '<a href="' . $fullImage[0] . '" class="woocommerce-variations-table-lightbox">' . $image . '</a>';
                    } else {
                        $html = $image; 
                    }

                    if($this->get_option('barcodeYith')) {
                        $html = do_shortcode('[yith_render_barcode product_id= ' . $variation->get_id() . ' ]') . $html;
                    }

                    break;
                case 'sk':
                    $html = $variation->get_sku();
                    break;
                case 'pr':

                    if($this->get_option('datatablesFiltering')) {
                        $html = strip_tags( wc_price( wc_get_price_to_display( $variation ) ) );
                    } else {
                        $html = wc_price( wc_get_price_to_display( $variation ) );
                    }

                    if($this->get_option('priceShowSalePrice')) {
                        $html = $variation->get_price_html();
                    }

                    break;
                case 'pt':
                    $html = apply_filters('the_title', $variation->get_name(), $variation->get_id());
                    break;
                case 'st':

                    $availability = $variation->get_availability();
                    if($variation->is_on_backorder( 1 )) {
                        $html = __('On Backorder', 'woocommerce-variations-table');
                    } elseif($variation->managing_stock()) {
                        $html = $availability['availability'];
                    } else {
                        if($variation->is_in_stock()) {
                            $html = __('In Stock', 'woocommerce-variations-table');
                        } else {
                            $html = __('Out of Stock', 'woocommerce-variations-table');
                        }
                    }
                    $html = '<span class="' . $variation->get_stock_status() . '">' . $html . '</span>';
                    // $html = '<p class="stock '. esc_attr( $class ) . '">'. wp_kses_post( $availability ) . '</p>';
                    break;
                case 'sq':
                    $html = $variation->get_stock_quantity() ? $variation->get_stock_quantity() : 0;
                    break;
                case 'de':
                    $html = $variation->get_description();
                    if($this->get_option('variationsTableDescriptionAutoP')) {
                        $html = wpautop($html);
                    }
                    break;
                case 'wi':
                    if($this->get_option('wishlistYith')) {
                        $html = do_shortcode('[yith_wcwl_add_to_wishlist product_id= ' . $variation->get_id() . ' ]');
                    } else {
                        $html = do_shortcode('[woocommerce_wishlist_button product= ' . $variation->get_id() . ' ]');
                    }
                    break;
                case 'di':
                    $html = wc_format_dimensions( $variation->get_dimensions(false) );
                    break;
                case 'wl':
                    $html = do_shortcode('[woocommerce_waitlist_notifier product_id="' . $variation->get_id() . '"]');
                    break;
                case 'at':
                    $html = $variation->get_variation_attributes();
                    break;
                case 'we':
                    $html = wc_format_weight( $variation->get_weight() );
                    break;
                case 'ca':
                    $html = $this->get_add_to_cart($variation);
                    break;
                case 'c1':
                    $html = $this->get_custom_text_field(1);
                    break;
                case 'c2':
                    $html = $this->get_custom_text_field(2);
                    break;
                case 'eq':
                    $html = $this->get_enquiry_button($variation);
                    break;
                case 'pd':
                    $html = $this->get_pdf_button($variation);
                    break;
                case 'mq':
                    global $product;
                    $product_id = $product->get_id();
                    $variation_id = $variation->get_id();

                    if(!$variation->is_in_stock()) {
                        $html = '<small class="woocommerce-variation-add-to-cart-out-of-stock">' . __('Out of Stock', 'woocommerce-variations-table') . '</small>';
                        break;
                    }

                    $variations = $variation->get_attributes();
                    $variation_string = "";
                    if(!empty($variations)) {
                        foreach ($variations as $key => $value) {
                            $variation_string .= $key . '=' . $value . ',';
                        }
                        $variation_string = rtrim($variation_string, ',');
                    }

                    $html = '<div class="variations-table-multiple-quantity-add-to-cart-products" data-product_id="' . $product_id . '" data-variation_id="' . $variation_id . '" data-variation="' . $variation_string . '">';
                        $html .= $this->get_multiple_quantity($variation);
                    $html .= '</div>';
                    break;
                case 'qt':
                    $html = $this->get_quantity($variation);
                    break;
                case 'mc':
                    global $product;
                    $product_id = $product->get_id();
                    $variation_id = $variation->get_id();

                    if(!$variation->is_in_stock()) {
                        $html = '<small class="woocommerce-variation-add-to-cart-out-of-stock">' . __('Out of Stock', 'woocommerce-variations-table') . '</small>';
                        break;
                    }

                    $variations = $variation->get_attributes();
                    $variation_string = "";
                    if(!empty($variations)) {
                        foreach ($variations as $key => $value) {
                            $variation_string .= $key . '=' . $value . ',';
                        }
                        $variation_string = rtrim($variation_string, ',');
                    }

                    $html = '<input type="checkbox" class="variations-table-multiple-add-to-cart-products" name="variations-table-multiple-add-to-cart-products" data-product_id="' . $product_id . '" data-variation_id="' . $variation_id . '" data-variation="' . $variation_string . '">';
                    break;
                default:
                    $variation_id = $variation->get_id();
                    $html = get_post_meta($variation_id, $key, true);
                    break;
            }
        }

        return $html;
    }

    /**
     * Get Variation Add to Cart
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @param   [type]                       $variation [description]
     * @return  [type]                                  [description]
     */
    public function get_add_to_cart($variation)
    {
        global $product;

        ob_start();
        $variations = $variation->get_attributes();
        $variation_string = "";
        if(!empty($variations)) {
            foreach ($variations as $key => $value) {
                $variation_string .= $key . '=' . $value . ',';
            }
            $variation_string = rtrim($variation_string, ',');
        }

        $outOfStock = false;
        if(!$variation->is_on_backorder( 1 ) && !$variation->is_in_stock()) {
            $outOfStock = true;
        }
        ?>
        
        <div class="woocommerce-variation-add-to-cart woocommerce-variations-table-add-to-cart variations_button">
            <?php if($outOfStock) { ?>
            <button type="submit" class=" button alt" disabled="disabled"><?php echo esc_html( $product->single_add_to_cart_text() ); ?></button>
            <small class="woocommerce-variation-add-to-cart-out-of-stock"><?php echo __('Out of Stock', 'woocommerce-variations-table'); ?></small>
            <?php } else { ?>
            <button type="submit" class=" button alt"><?php echo esc_html( $product->single_add_to_cart_text() ); ?></button>
            <?php } ?>
            <input type="hidden" name="add-to-cart" value="<?php echo absint( $product->get_id() ); ?>" />
            <input type="hidden" name="product_id" value="<?php echo absint( $product->get_id() ); ?>" />
            <input type="hidden" name="variation_id" class="variation_id" value="<?php echo $variation->get_id() ?>" />
            <input type="hidden" name="variation" class="variation" value="<?php echo $variation_string ?>" />
        </div>
        
        <?php

        $html = ob_get_contents();
        ob_end_clean();
        return $html;
    }

    public function get_custom_text_field($number)
    {   
        return '<input type="text" name="woocommerce_variations_table_custom_field_' . $number . '">';
    }

    public function get_enquiry_button($variation)
    {
        if(!class_exists('WooCommerce_Catalog_Mode')) {
            return;
        }

        global $woocommerce_catalog_mode_options;

        $buttonText = apply_filters('woocommerce_catalog_mode_enquiry_button_text', $woocommerce_catalog_mode_options['singleProductButtonText'] );

        $product_data = array(
            'name' => $variation->get_name(),
            'sku' => $variation->get_sku(),
        );
        $btnExtra = "data-products='" . json_encode($product_data). "'";

        ob_start();
        ?>
        <button type="button" class="enquiryLoopButton btn button btn-primary btn-lg" <?php echo $btnExtra ?>>
            <?php echo $buttonText ?>
        </button>
        
        <?php

        $html = ob_get_contents();
        ob_end_clean();
        return $html;
    }

    public function get_pdf_button($variation)
    {
        if(!class_exists('WooCommerce_Print_Products')) {
            return;
        }

        global $woocommerce_print_products_options;

        $buttonText = $woocommerce_print_products_options['iconTypeButtonPDFText'];

        $parentProductID = $variation->get_parent_id();
        $parentProductURL = get_permalink($parentProductID);
        $parentProductPDFExportURL = $parentProductURL . '?print-products=pdf&variation=' . $variation->get_id();

        ob_start();
        ?>
        <a type="button" href="<?php echo $parentProductPDFExportURL ?>" target="_blank" class="woocommerce-variations-table-pdf-export-button btn button btn-primary btn-lg">
            <?php echo $buttonText ?>
        </a>
        
        <?php

        $html = ob_get_contents();
        ob_end_clean();
        return $html;
    }

    /**
     * Get Variation Add to Cart
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @param   [type]                       $variation [description]
     * @return  [type]                                  [description]
     */
    public function get_quantity($variation)
    {
        global $product;

        if(!$variation->is_in_stock()) {
            return;
        }

        ob_start();
    
        do_action( 'woocommerce_before_add_to_cart_quantity' );

        woocommerce_quantity_input( array(
            'min_value'   => apply_filters( 'woocommerce_quantity_input_min', $variation->get_min_purchase_quantity(), $variation ),
            'max_value'   => apply_filters( 'woocommerce_quantity_input_max', $variation->get_max_purchase_quantity(), $variation ),
            'input_value' => isset( $_POST['quantity'] ) ? wc_stock_amount( $_POST['quantity'] ) : $variation->get_min_purchase_quantity(),
        ) );
        /**
         * @since 3.0.0.
         */
        do_action( 'woocommerce_after_add_to_cart_quantity' );

        $html = ob_get_contents();
        ob_end_clean();
        return $html;
    }

    public function get_multiple_quantity($variation)
    {
        global $product;

        ob_start();

        if(!$variation->is_in_stock()) {
            echo '<small class="woocommerce-variation-add-to-cart-out-of-stock">' . __('Out of Stock', 'woocommerce-variations-table') . '</small>';
            return;
        }       
    
        do_action( 'woocommerce_before_add_to_cart_quantity' );
        
        woocommerce_quantity_input( array(
            'min_value'   => 0,
            'max_value'   => apply_filters( 'woocommerce_quantity_input_max', $variation->get_max_purchase_quantity(), $variation ),
            'input_value' => 0,
        ) );

        /**
         * @since 3.0.0.
         */
        do_action( 'woocommerce_after_add_to_cart_quantity' );

        $html = ob_get_contents();
        ob_end_clean();
        return $html;
    }

    /**
     * Exclude Product Categories
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @return  [type]                       [description]
     */
    public function excludeProductCategories()
    {
        global $post;

        $f = false;

        $excludeProductCategories = $this->get_option('excludeProductCategories');
        $excludeProductCategoriesRevert = $this->get_option('excludeProductCategoriesRevert');
        $terms = get_the_terms( $post->ID, 'product_cat' );
        if($terms && !empty($excludeProductCategories))
        {
            
            foreach ($terms as $term)
            {
                if($excludeProductCategoriesRevert) {
                    if(in_array($term->term_id, $excludeProductCategories)){
                        return false;
                    } else {
                        $f = true;
                    }
                } else {
                    if(in_array($term->term_id, $excludeProductCategories)){
                        return TRUE;
                    }
                }
            }
        }

        return $f;
    }

    /**
     * Exclude Products
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @return  [type]                       [description]
     */
    public function excludeProducts()
    {
        global $post;

        $excludeProducts = $this->get_option('excludeProducts');
        $excludeProductsRevert = $this->get_option('excludeProductsRevert');
        if($excludeProductsRevert) {
            if(!in_array($post->ID, $excludeProducts))
            {
                return true;
            }
        } else {
            if(in_array($post->ID, $excludeProducts))
            {
                return true;
            }
        }
    }

    /**
     * Removes the add to cart button
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @return  [type]                       [description]
     */
    public function remove_add_to_cart()
    {
        global $product;

        if(!$product->is_type( 'variable' )) {
            return false;
        }

        if(!$this->get_option('removeDefaultVariations')) {
            return false;
        }

        remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
        remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
        remove_action( 'woocommerce_variable_add_to_cart', 'woocommerce_variable_add_to_cart', 30 );
    }

    /**
     * Hard Remove via CSS !important
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @return  [type]                       [description]
     */
    public function hardRemove()
    {
        echo '<style type="text/css">';

        echo 'table.variations .variations_button {
                    display:none !important;
                }';

        $excludeProductCategories = $this->get_option('excludeProductCategories');
        $excludeProducts = $this->get_option('excludeProducts');

        if(!empty($excludeProducts) || !empty($excludeProductCategories)) {

            if(!empty($excludeProductCategories)) 
            {
                $excludeProductCategoriesRevert = $this->get_option('excludeProductCategoriesRevert');
                if($excludeProductCategoriesRevert) {
                    $style = 'none';
                    echo 'table.variations .variations_button {
                                display:block !important;
                            }';
                } else {
                    $style = 'block';
                }

                foreach ($excludeProductCategories as $excludeProductCategory) {
                    $cat = get_term( $excludeProductCategory, 'product_cat' );
                    echo '.term-' . $excludeProductCategory . ' table.variations .variations_button, .term-' . $excludeProductCategory . ' table.variations .variations_button {
                        display: ' . $style . ' !important;
                    }';
                }
            }
            
            if(!empty($excludeProducts)) 
            {
                $excludeProductsRevert = $this->get_option('excludeProductsRevert');
                if($excludeProductsRevert) {
                    $style = 'none';
                    echo 'table.variations .variations_button {
                                display:block !important;
                            }';
                } else {
                    $style = 'block';
                }
                foreach ($excludeProducts as $excludeProduct) {
                    echo '.post-' . $excludeProduct . ' .table.variations .variations_button, .post-' . $excludeProduct . ' .table.variations .variations_button {
                        display: ' . $style . ' !important;
                    }';
                }
            }
        }

        echo '</style>';
    }

    /**
     * Return the current user role
     * @author Daniel Barenkamp
     * @version 1.0.0
     * @since   1.0.0
     * @link    https://www.welaunch.io
     * @return  [type]                       [description]
     */
    private function get_user_role()
    {
        global $current_user;

        $user_roles = $current_user->roles;
        $user_role = array_shift($user_roles);

        return $user_role;
    }

    public function add_to_cart()
    {
        ob_start();

        $cart_item_data = array();
        // $cart_item_data = (array) apply_filters( 'woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id );
        
        $multipleVariations = isset( $_POST['variations'] ) ? $_POST['variations'] : '';
        if(!empty($multipleVariations) && is_array($multipleVariations)) {
            foreach ($multipleVariations as $multipleVariation) {

                $product_id        = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $multipleVariation['product_id'] ) );
                $quantity          = empty( $multipleVariation['quantity'] ) ? 1 : wc_stock_amount( $multipleVariation['quantity'] );
                $variation_id      = isset( $multipleVariation['variation_id'] ) ? $multipleVariation['variation_id'] : '';
                $itemMetas = array();

                if(isset($multipleVariation['woocommerce_variations_table_custom_field_1']) && !empty($multipleVariation['woocommerce_variations_table_custom_field_1'])) {
                    $itemMetas['woocommerce_variations_table_custom_field_1'] = esc_html( $multipleVariation['woocommerce_variations_table_custom_field_1'] );
                }

                if(isset($multipleVariation['woocommerce_variations_table_custom_field_2']) && !empty($multipleVariation['woocommerce_variations_table_custom_field_2'])) {
                    $itemMetas['woocommerce_variations_table_custom_field_2'] = esc_html( $multipleVariation['woocommerce_variations_table_custom_field_2'] );
                }
               
                $attributes   = explode(',', $multipleVariation['variation']);
                $variation    = array();
                if(!empty($attributes)) {
                    foreach($attributes as $values){

                        $values = explode('=', $values);
                        if($this->get_option('oldThemeSupport')) {
                            $variation[$values[0]] = $values[1];
                        } else {
                            $variation['attribute_' . $values[0]] = $values[1];
                        }                           
                    }
                }

                $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variation, $cart_item_data );

                if ( $passed_validation) {
                    $added = WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $itemMetas );
                }
            }
        } else {

            $product_id        = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_POST['product_id'] ) );
            $quantity          = empty( $_POST['quantity'] ) ? 1 : wc_stock_amount( $_POST['quantity'] );
            $variation_id      = isset( $_POST['variation_id'] ) ? $_POST['variation_id'] : '';

            $itemMetas = array();

            if(isset($_POST['woocommerce_variations_table_custom_field_1']) && !empty($_POST['woocommerce_variations_table_custom_field_1'])) {
                $itemMetas['woocommerce_variations_table_custom_field_1'] = esc_html( $_POST['woocommerce_variations_table_custom_field_1'] );
            }

            if(isset($_POST['woocommerce_variations_table_custom_field_2']) && !empty($_POST['woocommerce_variations_table_custom_field_2'])) {
                $itemMetas['woocommerce_variations_table_custom_field_2'] = esc_html( $_POST['woocommerce_variations_table_custom_field_2'] );
            }
           
            $attributes   = explode(',', $_POST['variation']);
            $variation    = array();
            if(!empty($attributes)) {
                foreach($attributes as $values){
                    $values = explode('=', $values);
                    if($this->get_option('oldThemeSupport')) {
                        $variation[ urldecode($values[0]) ] =  urldecode($values[1]) ;
                    } else {
                        $variation['attribute_' . urldecode( $values[0] )] = urldecode( $values[1] );
                    }   
                }
            }

            $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variation, $cart_item_data );

            if ( $passed_validation) {
                $added = WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $itemMetas );
            }

        }
        

        do_action( 'woocommerce_ajax_added_to_cart', $product_id );

        if ( get_option( 'woocommerce_cart_redirect_after_add' ) == 'yes' ) {
            wc_add_to_cart_message( $product_id );
        }

        // Return fragments
        WC_AJAX::get_refreshed_fragments();

        die();
    }

    public function ajax_get_products()
    {
        global $product;

        $request = $_POST;

        if(!isset($request['product_id']) || empty($request['product_id'])) {
            die('Product ID missing');
        }

        $product = wc_get_product($request['product_id']);
        if(!$product) {
            die('Product not found');
        }

        $available_variations = $product->get_available_variations();
        $variationsTableData = apply_filters('woocommerce_variations_table_data', $this->get_option('variationsTableData') );

        $variationsTableData = $variationsTableData['enabled'];
        unset($variationsTableData['placebo']);

        $data = array();
        $i = 0;
        $index = 0;
        $available_variations_count = count($available_variations);

        $start = (int) isset($request['start']) && !empty($request['start']) ? $request['start'] : 0;
        $length = (int) isset($request['length']) && !empty($request['length']) ? $request['length'] : 0;
        $search = isset($request['search']) && !empty($request['search']['value']) ? esc_html( $request['search']['value'] ) : false;
        $order = isset($request['order'][0]) && !empty($request['order'][0]['column']) ? esc_html( $request['order'][0]['column'] ) : false;
        if($order) {
            $order_key = $request['columns'][$order]['data'];
        }
        $order_dir = isset($request['order'][0]) && !empty($request['order'][0]['dir']) ? esc_html( $request['order'][0]['dir'] ) : false;
        
        $searchData = array();
        foreach($request['columns'] as $column) {
            
            if(!isset($column['search'])) {
                continue;
            }

            if(!isset($column['search']['value']) || empty($column['search']['value'])) {
                continue;
            }

            $searchData[$column['data']] = array(
                'term' => htmlentities( str_replace('\\', '', $column['search']['value'] ) ),
                'regex' => $column['search']['regex'],
            );
        }

        foreach ($available_variations as $variation) {

            $variation_product = new WC_Product_Variation( $variation['variation_id'] );
            if(!$variation_product) {
                continue;
            }

            // $visible = apply_filters( 'woocommerce_variation_is_visible', $variation['variation_id'], $product, $variation_product);
            $visible = apply_filters( 'woocommerce_variation_is_visible', 'publish' === get_post_status( $variation_product->get_id() ) && '' !== $variation_product->get_price(), $variation_product->get_id(), $variation_product->get_parent_id(), $variation_product );
            if(!$visible) {
                continue;
            }

            if($this->get_option('hideOutOfStockVariations') && ( $variation_product->get_stock_quantity() < 1 || $variation_product->get_stock_status() == "outofstock") ) {
                continue;
            }

            if($start != 0 && $start > $index) {
                $index++;
                continue;
            }

            if($length > 0 && $i > $length) {
                break;
            }

            foreach($variationsTableData as $variationsTableDataKey => $variationsTableDataValue) {

                if($variationsTableDataKey == "at") {

                    foreach ($variation_product->get_attributes() as $attr_name => $attr_value) {

                        $attr_name = urldecode($attr_name);
                        $attr_value = urldecode($attr_value);
                        $original_attr_value = $attr_value;

                        $preselect = '';

                        // Get the correct variation values
                        if (strpos($attr_name, 'pa_') !== FALSE){ // variation is a pre-definted attribute
                            // $attr_name = substr($attr_name, 3);
                            $attr = get_term_by('slug', $attr_value, $attr_name);

                            // any attributes
                            if(!$attr) {
                                // continue;
                            }

                            if($attr) {
                                if(!empty($selected_attributes)) {
                                    if(isset($selected_attributes[$attr_name]) && $selected_attributes[$attr_name] == $attr_value){
                                        $preselect = 'data-preselect="' . apply_filters('woocommerce_attribute_value_image', esc_html( $attr->name ), $attr->term_id) . '"';
                                    }
                                }

                                $attr_value = apply_filters('woocommerce_attribute_value_image', esc_html( $attr->name ), $attr->term_id);
                                if(empty($attr_value) && isset($attr->name)) {
                                    $attr_value = $attr->name;
                                }
                            }
                            
                            $attr_label = wc_attribute_label($attr_name);

                        } else {
                            $attr = maybe_unserialize( get_post_meta( $product->get_id(), '_product_attributes' ) );
                            $attr_label = wc_attribute_label( $attr[0][$attr_name]['name'] );
                            
                        }

                        $data[$i][$attr_name] = $attr_value;
                    }
                } else {
                    $variationsTableDataDataValue = $this->getVariationData($variationsTableDataKey, $variation_product);

                    // data-order="' . (float) filter_var( str_replace(' - ', '', strip_tags($variationsTableDataDataValue) ), FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION ) . '"
                    $data[$i][$variationsTableDataKey] = $variationsTableDataDataValue;
                }
            }

            if(!empty($searchData)) {

                foreach($searchData as $searchDataKey => $searchDataValue) {
                        
                    if(!isset($data[$i][$searchDataKey])) {
                        continue;
                    }

                    $searchDataValueTerm = $searchDataValue['term'];

                    if($searchDataValue['regex']) {

                        if( !str_contains( strtolower( $data[$i][$searchDataKey] ), strtolower( $searchDataValueTerm) ) ) {
                            unset($data[$i]);
                            continue 2;
                        }

                    } else {

                        if( $data[$i][$searchDataKey] != $searchDataValueTerm ) {
                            unset($data[$i]);
                            continue 2;
                        }

                    }
                }

            }          

            $i++;
        }

        if(!empty($search)) {
            foreach($data as $dataKey => $dataValues) {
                $matches  = preg_grep('/' . $search . '/i', $dataValues);
                if(empty($matches)) {
                    unset($data[$dataKey]);
                }
            }
        }
 
        if(!empty($order_key) && is_array($data)) {
            $sortkey = array_column($data, $order_key);
            if($order_dir == "desc") {
                array_multisort($sortkey, SORT_DESC, $data);
            } else {
                array_multisort($sortkey, SORT_ASC, $data);
            }
        }

        $data = array_values($data);

        if(!empty($searchData) && !empty($search)) {
            $recordsFiltered = count($data);
        } else {
            $recordsFiltered = $available_variations_count;
        }
        

        $response = array(
            'recordsTotal' => $available_variations_count,
            'recordsFiltered' => $recordsFiltered,
            'data' => $data,
            'draw' => (int) $_POST['draw'],
        );

        echo json_encode( $response );
        wp_die();

    }
}