<?php
/**
* The admin-specific functionality of the plugin.
*
* Defines how Abandoned cart Table should be displayed
*
* @package    CartBounty Pro - Save and recover abandoned carts for WooCommerce
* @subpackage CartBounty Pro - Save and recover abandoned carts for WooCommerce/admin
* @author     Streamline.lv
*/

if( !class_exists( 'WP_List_Table' ) ){
	require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}

class CartBounty_Pro_Table extends WP_List_Table{

	/**
	 * The admin handler that manages the plugin's settings, options, and backend functionality.
	 *
	 * @since    10.9
	 * @access   protected
	 * @var      CartBounty_Pro_Admin    $admin    Provides methods to control and extend the plugin's admin area.
	 */
	protected $admin = null;

	/**
	 * The automation handler that manages the plugin's abandoned cart reminder automation functionality.
	 *
	 * @since    10.9
	 * @access   protected
	 * @var      CartBounty_Pro_Automation    $automation    Provides methods to control and extend the plugin's automations.
	 */
	protected $automation = null;

	/**
	 * Get the admin handler (lazy-loaded).
	 * Creates the connector on first use and then reuses the same instance.
	 *
	 * @since 10.9
	 * @access protected
	 * @return CartBounty_Pro_Admin
	 */
	protected function admin(){
		
		if( $this->admin === null ){
			$this->admin = new CartBounty_Pro_Admin( CARTBOUNTY_PRO_PLUGIN_NAME_SLUG, CARTBOUNTY_PRO_VERSION_NUMBER );
		}

		return $this->admin;
	}

	/**
	 * Get the automation handler (lazy-loaded).
	 * Creates the connector on first use and then reuses the same instance.
	 *
	 * @since 10.9
	 * @access protected
	 * @return CartBounty_Pro_Automation
	 */
	protected function automation(){
		
		if( $this->automation === null ){
			$this->automation = new CartBounty_Pro_Automation();
		}

		return $this->automation;
	}

	/**
	* Constructor, we override the parent to pass our own arguments
	* We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
	*
	* @since    1.0
	*/
	function __construct(){
		global $status, $page;

		parent::__construct(
			array(
				'singular'	=> 'id',
				'plural'	=> 'ids',
			)
		);
	}

	/**
	* This method return columns to display in table
	*
	* @since    1.0
	* @return   array
	*/
	function get_columns(){
		return $columns = array(
			'cb'			=>	'<input type="checkbox" />',
			'id'			=>	esc_html__('ID', 'woo-save-abandoned-carts'),
			'name'			=>	esc_html__('Name, Surname', 'woo-save-abandoned-carts'),
			'contact'		=>	esc_html__('Contact details', 'woo-save-abandoned-carts'),
			'location'		=>	esc_html__('Location', 'woo-save-abandoned-carts'),
			'cart_contents'	=>	esc_html__('Cart contents', 'woo-save-abandoned-carts'),
			'cart_total'	=>	esc_html__('Cart total', 'woo-save-abandoned-carts'),
			'time'			=>	esc_html__('Time', 'woo-save-abandoned-carts'),
			'status'		=>	esc_html__('Status', 'woo-save-abandoned-carts')
		);
	}

	/**
	* This method return columns that may be used to sort table
	* all strings in array - is column names
	* True on name column means that its default sort
	*
	* @since    1.0
	* @return   array
	*/
	public function get_sortable_columns(){						
		return $sortable = array(
			'id'			=>	array('id', true),
			'name'			=>	array('name', true),
			'cart_total'	=>	array('cart_total', true),
			'time'			=>	array('time', true)
		);
	}

	/**
	* This is a default column renderer
	*
	* @since    1.0
	* @param    $item - row (key, value array)
	* @param    $column_name - string (key)
	* @return   HTML
	*/
	function column_default( $item, $column_name ){
		return $item[$column_name];
	}

	/**
	* Rendering Name column
	*
	* @since    1.0
	* @return   HTML
	* @param    $item - row (key, value array)
	*/
	function column_name( $item ){
		$admin = $this->admin();
		$cart_status = 'all';
		$actions = array();
		$name_array = array();
		$paged = false;
		$orderby = false;
		$order = false;
		$user = false;
		$tab = $admin->get_open_tab();

		if ( isset( $_GET['cart-status'] ) ){
			$cart_status = $_GET['cart-status'];
		}

		if ( isset( $_GET['paged'] ) ){
			$paged = '&paged=' . $_GET['paged'];
		}

		if ( isset( $_GET['orderby'] ) ){
			$orderby = '&orderby=' . $_GET['orderby'];
		}

		if ( isset( $_GET['order'] ) ){
			$order = '&order=' . $_GET['order'];
		}

		if( ( !empty( $item['email'] ) || !empty( $item['phone'] ) || !empty( $item['pn_subscription'] ) ) && $item['anonymized'] == 0 && $item['type'] != $admin->get_cart_type('recovered') ){

			$action_name = 'pause';
			$link_name = esc_html__( 'Pause', 'woo-save-abandoned-carts' );

			if( $item['paused'] ){
				$action_name = 'resume';
				$link_name = esc_html__( 'Resume', 'woo-save-abandoned-carts' );
			}

			$pause_resume_url = '?page='. esc_attr( $_REQUEST['page'] ) .'&tab='. $tab .'&action='. $action_name .'&id='. esc_attr( $item['id'] ) .'&cart-status='. esc_attr( $cart_status ) . esc_attr( $orderby ) . esc_attr( $order ) . esc_attr( $paged );
			$actions[$action_name] = sprintf( '<a href="%s">%s</a>', esc_url( $pause_resume_url ), $link_name );
		}

		if( $admin->user_is_admin() ){
			$nonce = wp_create_nonce( 'delete_cart_nonce' );
			$delete_url = '?page='. esc_attr( $_REQUEST['page'] ) .'&tab='. $tab .'&action=delete&id='. esc_attr( $item['id'] ) .'&cart-status='. esc_attr( $cart_status ) . esc_attr( $orderby ) . esc_attr( $order ) . esc_attr( $paged ) .'&nonce='. $nonce;
			$actions['delete'] = sprintf( '<a href="%s">%s</a>', esc_url( $delete_url ), esc_html__( 'Delete', 'woo-save-abandoned-carts' ) );
		}

		if( !empty( $item['name'] ) ){
			$name_array[] = $item['name'];
		}

		if( !empty( $item['surname'] ) ){
			$name_array[] = $item['surname'];
		}

		$name = esc_html( stripslashes( implode( ' ', $name_array ) ) );

		if( isset( $item['email'] ) ){
			$user = get_user_by( 'email', $item['email'] );
		}

		if( $user ){ //If the user is registered, add link to his profile page
			$name = '<a href="' . esc_url( add_query_arg( 'user_id', $user->ID, self_admin_url( 'user-edit.php' ) ) ) . '" title="' . esc_attr__( 'View user profile', 'woo-save-abandoned-carts' ) . '">'. $name .'</a>';
		}

		$user_icon = '<svg class="cartbounty-pro-customer-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 65.77 82.92"><path d="M32.89,41.8a20.9,20.9,0,1,1,20.9-20.9A20.92,20.92,0,0,1,32.89,41.8Zm0-32.8a11.9,11.9,0,1,0,11.9,11.9A11.91,11.91,0,0,0,32.89,9Z"/><path d="M47.46,82.92H18.31a18.32,18.32,0,0,1,0-36.63H47.46a18.32,18.32,0,0,1,0,36.63ZM18.31,55.29a9.32,9.32,0,0,0,0,18.63H47.46a9.32,9.32,0,0,0,0-18.63Z"/></svg>';

		if( !empty( $item['email'] ) || !empty( $item['phone'] ) || !empty( $item['pn_subscription'] ) ){ //If we have phone, email or push notification subscription
			$user_icon = '<svg class="cartbounty-pro-customer-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 55.77 70"><path d="M42,42.37H13.81a13.82,13.82,0,0,0,0,27.63H42a13.82,13.82,0,0,0,0-27.63Z"/><path d="M27.89,32.8a16.4,16.4,0,1,0-16.4-16.4A16.4,16.4,0,0,0,27.89,32.8Z"/></svg>';
		}

		return sprintf( '%s%s %s',
			$user_icon,
			$name,
			$this->row_actions( $actions )
		);
	}

	/**
	* Rendering Contact info column
	*
	* @since    9.9.1
	* @return   HTML
	* @param    $item - row (key, value array)
	*/
	function column_contact( $item ){
		$contact_details = array();

		if( !empty( $item['email'] ) ){
			$contact_details[] = '<p><a href="'. esc_url( 'mailto:' . $item['email'] ) .'">'. esc_html( $item['email'] ) .'</a></p>';
		}

		if( !empty( $item['phone'] ) ){
			$contact_details[] = '<p>'. esc_html( $item['phone'] ) .'</p>';
		}

		if( !empty( $item['pn_subscription'] ) ){
			$contact_details[] = '<p class="cartbounty-pro-dimmed">'. esc_html__( 'Push notification' ) .'</p>';
		}

		$data = implode( '', $contact_details );
		return sprintf( '%s', $data );
	}

	/**
	* Rendering Location column
	*
	* @since    6.8
	* @return   HTML
	* @param    $item - row (key, value array)
	*/
	function column_location( $item ){
		$admin = $this->admin();
		$location_array = array();
		$address_1 = '';
		$address_2 = '';
		$state = '';

		$location_data = $admin->get_cart_location( $item['location'] );
		$country = $location_data['country'];
		$city = $location_data['city'];
		$postcode = $location_data['postcode'];

		if( $country && class_exists( 'WooCommerce' ) ){ //In case WooCommerce is active and we have Country data, we can add abbreviation to it with a full country name
			$country = '<abbr class="cartbounty-pro-country" title="' . esc_attr( WC()->countries->countries[ $country ] ) . '">' . esc_html( $country ) . '</abbr>';
		}

		if( apply_filters( 'cartbounty_pro_display_full_address', false ) ){ //Provide full address fields in case filter enabled

			$other_fields = maybe_unserialize( $item['other_fields'] );

			if( $other_fields ){
				$address_1 = $other_fields['cartbounty_pro_billing_address_1'];
				$address_2 = $other_fields['cartbounty_pro_billing_address_2'];
				$state = $other_fields['cartbounty_pro_billing_state'];
			}
		}

		//Building address output array
		if( !empty( $address_1 ) ){
			$location_array[] = $address_1;
		}

		if( !empty( $address_2 ) ){
			$location_array[] = $address_2;
		}

		if( !empty( $city ) ){
			$location_array[] = $city;
		}

		if( !empty( $state ) ){
			$divider = '';

			if( !empty( $postcode ) ){
				$divider = ' ';
			}

			$location_array[] = $state . $divider . $postcode;

		}else{

			if( !empty( $postcode ) ){
				$location_array[] = $postcode;
			}
		}

		if( !empty( $country ) ){
			$location_array[] = $country;
		}

		$location = stripslashes( implode( ', ', $location_array ) );
		return sprintf( '%s', $location );
	}

	/**
	* Rendering Cart Contents column
	*
	* @since    1.0
	* @return   HTML
	* @param    $item - row (key, value array)
	*/
	function column_cart_contents( $item ){
		$admin = $this->admin();
		$cart_contents = $admin->get_saved_cart_contents( $item['cart_contents'] );
		$output = '';

		if( $cart_contents ){

			if( $admin->get_settings( 'settings', 'hide_images' ) ){ //Outputting Cart contents as a list
				$output = '<ol class="cartbounty-pro-product-list">';

				foreach( $cart_contents as $product ){

					if( is_array( $product ) ){

						if( isset( $product['product_title'] ) ){
							$product_title = esc_html( $product['product_title'] );
							$quantity = " (". $product['quantity'] .")"; //Enclose product quantity in brackets
							$edit_product_link = get_edit_post_link( $product['product_id'], '&' ); //Get product link by product ID
							$product_price = $admin->get_product_price( $product );
							$price = ', ' . $admin->format_price( $product_price, esc_html( $item['currency'] ) );
							$product_title_line = $product_title . $price . $quantity;
							$output .= '<li>';

							if( $edit_product_link ){ //If link exists (meaning the product hasn't been deleted)
								$output .= '<a href="'. esc_url( $edit_product_link ) .'" title="'. esc_attr( $product_title ) .'" target="_blank">'. esc_html( $product_title_line ) .'</a>';

							}else{
								$output .= esc_html( $product_title_line );
							}

							//Handle WooCommerce Product Bundles plugin data
							if( !empty( $product['bundle_data'] ) ){
								$bundle_data = $product['bundle_data'];

								if( $bundle_data ){
									$output .= '<ul>';

									foreach ( $bundle_data as $key => $bundle_item ){
										$bundle_item_title = '';
										$bundle_quantity = '';

										//In case dealing with variable bundle item, get selected variation name
										if( isset( $bundle_item['variation_id'] ) ){
											$bundle_item_variation_title = get_the_title( $bundle_item['variation_id'] );
											$bundle_item_title = $bundle_item_variation_title;
										}

										//Handling regular item name
										if( empty( $bundle_item_title ) ){

											if( isset( $bundle_item['title'] ) ){ //If bundle has custom title, use it
												$bundle_item_title = $bundle_item['title'];

											}else{ //Using default product title
												$bundle_item_title = get_the_title( $bundle_item['product_id'] );
											}
										}

										if( !empty( $bundle_item_title ) ){

											if( isset( $bundle_item['quantity'] ) ){
												$bundle_quantity = " (". $bundle_item['quantity'] .")"; //Enclose product quantity in brackets
											}

											$output .= '<li>' . esc_html( $bundle_item_title ) . esc_html( $bundle_quantity ) . '</li>';
										}
									}
									$output .= '</ul>';
								}
							}
							$output .= '</li>';
						}
					}
				}
				
				$output .= '</ol>';

			}else{ //Displaying cart contents with thumbnails

				foreach( $cart_contents as $product ){

					if( is_array( $product ) ){

						if( isset( $product['product_title'] ) ){

							//Checking product image
							$image_url = $admin->get_product_thumbnail_url( $product, 'thumbnail' );
							$product_title = esc_html( $product['product_title'] );
							$quantity = " (". $product['quantity'] .")"; //Enclose product quantity in brackets
							$edit_product_link = get_edit_post_link( $product['product_id'], '&' ); //Get product link by product ID
							$product_price = $admin->get_product_price( $product );
							$price = ', ' . $admin->format_price( $product_price, esc_html( $item['currency'] ) );
							$output .= '<div class="cartbounty-pro-abandoned-product"><span class="cartbounty-pro-tooltip">'. esc_html( $product_title ) . esc_html( $price ) . esc_html( $quantity ) .'</span>';
							$product_image = '<img src="'. esc_url( $image_url ) .'" title="'. esc_attr( $product_title ) .'" alt ="'. esc_attr( $product_title ) .'" />';

							if( $edit_product_link ){ //If link exists (meaning the product hasn't been deleted)
								$output .= '<a href="'. esc_url( $edit_product_link ) .'" title="'. esc_attr( $product_title ) .'" target="_blank">' . $product_image . '</a>';

							}else{
								$output .= $product_image;
							}

							$output .= '</div>';
						}
					}
				}
			}
		}

		return sprintf( '%s', $output );
	}

	/**
	* Rendering Cart Total column
	*
	* @since    1.0
	* @return   HTML
	* @param    $item - row (key, value array)
	*/
	function column_cart_total( $item ){
		return sprintf('%0.2f %s',
			esc_html( $item['cart_total'] ),
			esc_html( $item['currency'] )
		);
	}

	/**
	* Render Time column 
	*
	* @since    1.0
	* @return   HTML
	* @param    $item - row (key, value array)
	*/
	function column_time( $item ){
		$time = new DateTime( $item['time'], new DateTimeZone( 'UTC' ) );
		$ts_utc = $time->getTimestamp();
		$now_utc = current_time( 'timestamp', true );
		$friendly = wp_date( 'M d, Y', $ts_utc );
		$date_iso = gmdate( 'c', $ts_utc );
		$date_title = wp_date( 'M d, Y H:i:s', $ts_utc );
		
		if( $ts_utc > ( $now_utc - DAY_IN_SECONDS ) ){
			$friendly = sprintf(
				esc_html__( '%1$s ago', 'woo-save-abandoned-carts' ),
				human_time_diff( $ts_utc, $now_utc )
			);
		}

		return sprintf(
			'<svg class="cartbounty-pro-time-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 31.18 31.18"><path d="M15.59,31.18A15.59,15.59,0,1,1,31.18,15.59,15.6,15.6,0,0,1,15.59,31.18Zm0-27.34A11.75,11.75,0,1,0,27.34,15.59,11.76,11.76,0,0,0,15.59,3.84Z"/><path d="M20.39,20.06c-1.16-.55-6-3-6.36-3.19s-.46-.76-.46-1.18V7.79a1.75,1.75,0,1,1,3.5,0v6.88s4,2.06,4.8,2.52a1.6,1.6,0,0,1,.69,2.16A1.63,1.63,0,0,1,20.39,20.06Z"/></svg><time datetime="%s" title="%s">%s</time>',
			esc_attr( $date_iso ),
			esc_attr( $date_title ),
			esc_html( $friendly )
		);
	}

	/**
	* Rendering Status column
	*
	* @since    1.0
	* @return   HTML
	* @param    $item - row (key, value array)
	*/
	function column_status( $item ){
		$admin = $this->admin();
		$automation = $this->automation();
		$cart_time = strtotime($item['time']);
		$date = date_create( current_time( 'mysql', true ) );
		$current_time = strtotime(date_format($date, 'Y-m-d H:i:s'));
		$status = '';
		$cart_recovered = false;
		$cart_waiting_time = $admin->get_waiting_time();

		if($item['type'] == $admin->get_cart_type('recovered')){
			$status .= sprintf('<span class="status recovered">%s</span>', esc_html__('Recovered', 'woo-save-abandoned-carts'));
			$cart_recovered = true;
		}

		if($cart_time > $current_time - $cart_waiting_time * 60 && $item['type'] != $admin->get_cart_type('recovered')){ //Checking time if user is still shopping or might return - we add shopping label
			$status_description = sprintf( esc_html__( 'Will be considered abandoned after %s minutes of no activity', 'woo-save-abandoned-carts' ),  $cart_waiting_time );
			$status .= sprintf( '<div class="status-item-container shopping-description"><span class="cartbounty-pro-tooltip">%s</span><span class="status shopping">%s</span></div>', $status_description, esc_html__( 'Shopping', 'woo-save-abandoned-carts' ) );

		}else{

			if($cart_time > ($current_time - CARTBOUNTY_PRO_NEW_NOTICE * 60 )){ //Checking time if user has not gone through with the checkout after the specified time we add new label
				$status_description = esc_html__('Recently abandoned', 'woo-save-abandoned-carts');
				if($item['type'] == $admin->get_cart_type('recovered')){
					$status_description = esc_html__('Recently recovered', 'woo-save-abandoned-carts');
				}
				$status .= sprintf('<div class="status-item-container"><span class="cartbounty-pro-tooltip">%s</span><span class="status new">%s</span></div>', $status_description, esc_html__('New', 'woo-save-abandoned-carts'));
			}

			if($item['mc_synced']){
				$status .= sprintf('<div class="status-item-container"><span class="cartbounty-pro-tooltip">%s</span><span class="status synced mailchimp">MC</span></div>', esc_html__('Synchronized to MailChimp', 'woo-save-abandoned-carts') );
			}
			if($item['ac_cart_id']){
				$status .= sprintf('<div class="status-item-container"><span class="cartbounty-pro-tooltip">%s</span><span class="status synced activecampaign">AC</span></div>', esc_html__('Synchronized to ActiveCampaign', 'woo-save-abandoned-carts') );
			}
			if($item['gr_cart_id']){
				$status .= sprintf('<div class="status-item-container"><span class="cartbounty-pro-tooltip">%s</span><span class="status synced getresponse">GR</span></div>', esc_html__('Synchronized to GetResponse', 'woo-save-abandoned-carts') );
			}
			if($item['wp_steps_completed']){
			$message_history = $automation->display_message_history( 'wordpress', $item['id'], $cart_recovered ); //Getting email history of current cart
			$status .= sprintf('<div class="status-item-container message-history%s"><span class="cartbounty-pro-tooltip">%s%s</span><span class="status synced wordpress">WP</span></div>', ( $message_history['has_extra_details'] ) ? ' extra-details' : '', esc_html__('Sent via WordPress', 'woo-save-abandoned-carts'), $message_history['data'] );
			}
			if($item['sms_steps_completed']){
			$message_history = $automation->display_message_history( 'bulkgate', $item['id'], $cart_recovered ); //Getting message history of current cart
			$status .= sprintf('<div class="status-item-container message-history%s"><span class="cartbounty-pro-tooltip">%s%s</span><span class="status synced bulkgate">BG</span></div>', ( $message_history['has_extra_details'] ) ? ' extra-details' : '', esc_html__('Sent via BulkGate', 'woo-save-abandoned-carts'), $message_history['data'] );
			}
			if($item['pn_steps_completed']){
			$message_history = $automation->display_message_history( 'push_notification', $item['id'], $cart_recovered ); //Getting message history of current cart
			$status .= sprintf('<div class="status-item-container message-history%s"><span class="cartbounty-pro-tooltip">%s%s</span><span class="status synced push-notification">PN</span></div>', ( $message_history['has_extra_details'] ) ? ' extra-details' : '', esc_html__('Sent via Push notification', 'woo-save-abandoned-carts'), $message_history['data'] );
			}
			if($item['wh_last_synced'] != '0000-00-00 00:00:00'){
				$status .= sprintf('<div class="status-item-container"><span class="cartbounty-pro-tooltip">%s</span><span class="status synced webhook">WH</span></div>', esc_html__('Sent to webhook', 'woo-save-abandoned-carts') );
			}
		}

		if($item['saved_via'] == 1){ //If cart saved via Exit Intent
			$status .= sprintf('<div class="status-item-container tool"><span class="cartbounty-pro-tooltip">%s</span><span class="status tool-saved saved-by-exit-intent">EI</span></div>', esc_html__('Saved by Exit Intent', 'woo-save-abandoned-carts') );

		}elseif($item['saved_via'] == 2){ //If cart saved via Early capture
			$status .= sprintf('<div class="status-item-container tool"><span class="cartbounty-pro-tooltip">%s</span><span class="status tool-saved saved-by-early-capture">EC</span></div>', esc_html__('Saved by Early capture', 'woo-save-abandoned-carts') );

		}elseif($item['saved_via'] == 3){ //If cart saved via custom field
			$status .= sprintf('<div class="status-item-container tool"><span class="cartbounty-pro-tooltip">%s</span><span class="status tool-saved saved-by-custom-field">CF</span></div>', esc_html__('Saved by custom field', 'woo-save-abandoned-carts') );
		}

		if( $item['paused'] ){
			$status .= sprintf( '<div class="status-item-container tool"><span class="cartbounty-pro-tooltip">%s</span><span class="status tool-saved recovery-paused">PA</span></div>', esc_html__( 'Recovery paused', 'woo-save-abandoned-carts' ) );
		}

		if( $item['restarts'] ){
			$status .= sprintf( '<div class="status-item-container tool"><span class="cartbounty-pro-tooltip">%s</span><span class="status tool-saved recovery-restarted">RS</span></div>', sprintf( esc_html( _n( 'Recovery restarted %d time', 'Recovery restarted %d times', $item['restarts'], 'woo-save-abandoned-carts' ) ), $item['restarts'] ) );
		}

		return $status;
	}

	/**
	* Rendering checkbox column
	*
	* @since    1.0
	* @return   HTML
	* @param    $item - row (key, value array)
	*/
	function column_cb( $item ){
		return sprintf(
			'<input type="checkbox" name="id[]" value="%s" />',
			esc_attr( $item['id'] )
		);
	}

	/**
	* Return array of bulk actions if we have any
	*
	* @since    1.0
	* @return   array
	*/
	function get_bulk_actions(){
		$admin = $this->admin();
		$actions = array(
			'pause'		=> esc_html__( 'Pause recovery', 'woo-save-abandoned-carts' ),
			'resume'	=> esc_html__( 'Resume recovery', 'woo-save-abandoned-carts' ),
			'restart'	=> esc_html__( 'Restart recovery', 'woo-save-abandoned-carts' ),
			'delete'	=> esc_html__( 'Delete', 'woo-save-abandoned-carts' )
		);

		if( !$admin->user_is_admin() ){ //If the user is not Admin, remove delete option
			unset( $actions['delete'] );
		}

		return $actions;
	}

	/**
	* Processing Bulk actions and single actions
	*
	* @since    1.0
	*/
	function process_bulk_action(){

		if( empty( $_REQUEST['id'] ) ) return; //Exit in case no row selected

		$cart_id = isset( $_REQUEST['id'] ) ? $_REQUEST['id'] : array();

		if( empty( $cart_id ) ) return;

		global $wpdb;
		$admin = $this->admin();
		$mailchimp = new CartBounty_Pro_Mailchimp();
		$getresponse = new CartBounty_Pro_GetResponse();
		$webhook = new CartBounty_Pro_Webhook();
		$cart_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME;
		$processed_rows = 0;

		if( 'delete' === $this->current_action() ) {

			if( !$admin->user_is_admin() ){
				wp_die( esc_html__( 'You do not have sufficient permissions to perform this action.', 'woo-save-abandoned-carts' ) );
			}

			$mailchimp->delete_cart( $cart_id );
			$activecampaign = new CartBounty_Pro_ActiveCampaign();
			$webhook->delete_cart( $cart_id );

			if( $activecampaign->store_connected() ){

				if( is_array( $cart_id ) ){
					$limitationst = 0;
					foreach( $cart_id as $key => $id ){

						if( $limit > 1 ){ //Limit delete requests to ActiveCampaign sync due to speed limitations
							break;
						}

						$ac_contact_id = $activecampaign->get_ac_contact_id( $id );
						$activecampaign->remove_contact_from_automation( $ac_contact_id );
						$limit++;
					}

				}else{
					$id = $cart_id;
					$ac_contact_id = $activecampaign->get_ac_contact_id( $id );
					$activecampaign->remove_contact_from_automation( $ac_contact_id );
				}
			}

			if( $getresponse->store_connected() ){

				if( is_array( $cart_id ) ){
					$limit = 0;
					foreach( $cart_id as $key => $id ){

						if( $limit > 1 ){ //Limit delete requests to GetResponse sync due to speed limitations
							break;
						}

						$gr_cart_id = $getresponse->get_gr_cart_id( $id );
						$getresponse->delete_cart( $gr_cart_id, $id );
						$limit++;
					}

				}else{
					$id = $cart_id;
					$gr_cart_id = $getresponse->get_gr_cart_id( $id );
					$getresponse->delete_cart( $gr_cart_id, $id );
				}

			}

			if( is_array( $cart_id ) ){ //Bulk abandoned cart deletion
				foreach( $cart_id as $key => $id ){
					$processed_rows += $admin->delete_cart( $id );
				}

			}else{ //Single abandoned cart deletion
				$id = $cart_id;
				$processed_rows = $admin->delete_cart( $id );
			}

		}elseif( 'pause' === $this->current_action() ){

			if( is_array( $cart_id ) ){ //Bulk pause abandoned cart recovery
				foreach( $cart_id as $key => $id ){
					$processed_rows += $admin->pause_cart( $id );
				}

			}else{ //Single pause abandoned cart recovery
				$id = $cart_id;
				$processed_rows = $admin->pause_cart( $id );
			}

		}elseif( 'resume' === $this->current_action() ){

			if( is_array( $cart_id ) ){ //Bulk resume abandoned cart recovery
				foreach( $cart_id as $key => $id ){
					$processed_rows += $admin->resume_cart( $id );
				}

			}else{ //Single resume abandoned cart recovery
				$id = $cart_id;
				$processed_rows = $admin->resume_cart( $id );
			}

		}elseif( 'restart' === $this->current_action() ){

			if( is_array( $cart_id ) ){ //Bulk abandoned cart recovery restart
				foreach( $cart_id as $key => $id ){
					$processed_rows += $admin->restart_cart( $id );
				}

			}else{ //Single abandoned cart recovery restart
				$id = $cart_id;
				$processed_rows = $admin->restart_cart( $id );
			}
		}

		$_REQUEST['processed_rows'] = $processed_rows;
	}

	/**
	* Method that renders the table
	*
	* @since    1.0
	*/
	function prepare_items(){
		global $wpdb;
		$admin = $this->admin();
		$cart_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME;

		$cart_status = 'all';
		if (isset($_GET['cart-status'])){
			$cart_status = $_GET['cart-status'];
		}

		$screen = get_current_screen();
		$user = get_current_user_id();
		$option = $screen->get_option('per_page', 'option');
		$per_page = get_user_meta($user, $option, true);

		//How much records will be shown per page, if the user has not saved any custom values under Screen options, then default amount of 10 rows will be shown
		if ( is_array($per_page) || $per_page < 1 ) {
			$per_page = 10;
		}

		$columns = $this->get_columns();
		$hidden = array();
		$sortable = $this->get_sortable_columns();
		$this->_column_headers = array($columns, $hidden, $sortable); // here we configure table headers, defined in our methods
		$this->process_bulk_action(); //Process bulk action if any
		$total_items = $admin->get_cart_count($cart_status, $search = true);

		//Configure pagination
		$this->set_pagination_args(
			array(
				'total_items'	=> $total_items, // total items defined above
				'per_page'		=> $per_page, // per page constant defined at top of method
				'total_pages'	=> ceil($total_items / $per_page) // calculate pages count
			)
		);

		$paged = isset($_REQUEST['paged']) ? max(0, intval($_REQUEST['paged']) - 1) : 0;
		$orderby = (isset($_REQUEST['orderby']) && in_array($_REQUEST['orderby'], array_keys($this->get_sortable_columns()))) ? $_REQUEST['orderby'] : 'time';
		$order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'desc';

		$search_query = '';
		$variables = array(
			$per_page,
			$paged * $per_page
		);
		$search_handle_data = $admin->handle_search( $variables, 'front' );
		
		if($search_handle_data){
			$search_query = $search_handle_data['query'];
			$variables = $search_handle_data['variables'];
		}

		$where_sentence = $admin->get_where_sentence( $cart_status );
		$this->items = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT
				id,
				name,
				surname,
				email,
				phone,
				location,
				cart_contents,
				cart_total,
				currency,
				time,
				mc_synced,
				ac_cart_id,
				gr_cart_id,
				wp_steps_completed,
				sms_steps_completed,
				wh_last_synced,
				pn_subscription,
				pn_steps_completed,
				paused,
				restarts,
				type,
				saved_via,
				anonymized
				FROM $cart_table
				WHERE cart_contents != ''
				$where_sentence
				$search_query
				ORDER BY $orderby $order
				LIMIT %d OFFSET %d",
				$variables
			), ARRAY_A
		);
	}
}