<?php
/**
 * The WordPress class
 *
 * Used to define WordPress email related functions
 *
 *
 * @since      9.3
 * @package    CartBounty Pro - Save and recover abandoned carts for WooCommerce
 * @subpackage CartBounty Pro - Save and recover abandoned carts for WooCommerce/includes
 * @author     Streamline.lv
 */
class CartBounty_Pro_WordPress{
	
	/**
	 * 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 public handler that manages the plugin's settings, options, and frontend functionality.
	 *
	 * @since    10.9
	 * @access   protected
	 * @var      CartBounty_Pro_Public    $public    Provides methods to control and extend the plugin's public area.
	 */
	protected $public = 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 public handler (lazy-loaded).
	 * Creates the connector on first use and then reuses the same instance.
	 *
	 * @since 10.9
	 * @access protected
	 * @return CartBounty_Pro_Public
	 */
	protected function public(){
		
		if( $this->public === null ){
			$this->public = new CartBounty_Pro_Public( CARTBOUNTY_PRO_PLUGIN_NAME_SLUG, CARTBOUNTY_PRO_VERSION_NUMBER );
		}

		return $this->public;
	}

	/**
	 * 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;
	}

	/**
	* Retrieve WordPress recovery settings
	*
	* @since    10.1
	* @return   array
	* @param    string     $value                Value to return
	*/
	public function get_settings( $value = false ){
		$saved_options = get_option( 'cartbounty_pro_automation_settings' );
		$defaults = array(
			'from_name' 		=> '',
			'from_email' 		=> '',
			'reply_email' 		=> false,
		);

		if( is_array( $saved_options ) ){
			$settings = array_merge( $defaults, $saved_options ); //Merging default settings with saved options
			
		}else{
			$settings = $defaults;
		}

		if( $value ){ //If a single value should be returned
			
			if( isset( $settings[$value] ) ){ //Checking if value exists
				$settings = $settings[$value];
			}
		}

		return $settings;
	}

	/**
	 * Starting WordPress email automation process
	 *
	 * @since    9.3
	 */
	public function auto_send(){
		$admin = $this->admin();
		$automation = $this->automation();

		if( !$admin->check_license() || !class_exists( 'WooCommerce' ) ) return;
			
		if( $automation->automation_enabled( 'wordpress' ) ){
			$this->recover_carts();
		}
	}

	/**
	 * Starting abandoned cart recovery
	 *
	 * @since    9.3
	 */
	private function recover_carts(){
		global $wpdb;
		$admin = $this->admin();
		$automation = $this->automation();

		$cart_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME;
		$time = $admin->get_time_intervals();
		$email_consent_query = '';

		if( $admin->get_consent_settings( 'email' ) ){ //Check if email consent enabled to query only carts with given email usage consent
			$email_consent_query = 'AND email_consent = 1';
		}

		//Retrieving all abandoned carts that are eligible for email recovery
		//Excluding finished automations, unsubscribed carts and excluded carts (ones that have been manually removed from automation)
		$carts = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT id, email, phone, name, surname, session_id, location, cart_contents, cart_total, currency, time, language, wp_steps_completed, wp_last_sent
				FROM {$cart_table}
				WHERE (type = %d OR type = %d) AND
				email != '' AND
				cart_contents != '' AND
				wp_unsubscribed != 1 AND
				paused != 1 AND
				wp_excluded != 1 AND
				wp_complete != 1 AND
				anonymized != 1 AND
				time < %s AND
				time > %s
				$email_consent_query",
				$admin->get_cart_type( 'abandoned' ),
				$admin->get_cart_type( 'recovered_pending' ),
				$time['cart_abandoned'],
				$time['maximum_sync_period']
			)
		);

		$active_steps = $automation->get_active_steps( 'wordpress' );
		$automation_steps = get_option( 'cartbounty_pro_automation_steps' );
		$messages_sent = 0;
		$max_messages_to_send = apply_filters( 'cartbounty_pro_wordpress_batch_email_limit', 10 );

		foreach( $active_steps as $key => $step ){ //Looping through active steps
			$automation_step = $automation_steps[$step];
			
			foreach( $carts as $cart_key => $cart ){

				//If sent message limit reached, break out of both foreach loops
				if( $messages_sent >= $max_messages_to_send ){
					break 2;
				}
				
				if( $cart->wp_steps_completed == $key ){ //If current step must be complete
					$first_step = false;
					$time = $cart->wp_last_sent;
					
					if( $cart->wp_steps_completed == 0 ){ //If reminder about current cart has never been sent - use cart capture time instead of last step automation sent time
						$time = $cart->time;
						$first_step = true;
					}

					if( isset( $automation_step['interval'] ) ){
						$interval = $automation_step['interval'];

					}else{ //If custom interval is not set, fallback to default interval
						$interval = $this->get_defaults( 'interval', $step );
					}
					
					$step_wait_time = $admin->get_time_intervals( $interval, $first_step ); //Get time interval for the current step

					if ($time < $step_wait_time['wp_step_send_period']){ //Check if time has passed for current step

						if( !$admin->has_excluded_items( $cart, 'wordpress' ) ){ //If cart contents do not have excluded items
							$this->send_reminder( $cart, $key ); //Time has passed - must prepare and send out reminder email
							$messages_sent++;
						
						}else{
							$admin->exclude_cart( 'wordpress', $cart ); //Exclude cart from further recovery
						}

						unset( $carts[$cart_key] ); //Remove array element so the next step loop runs faster
					}
				}
			}
		}
	}

	/**
	 * Send email reminder
	 * Send out email reminder according to selecte template, subject, contents
	 * Create a new row in emails table
	 * Update abandoned cart last sent time, completed steps and if the automation is completed or not
	 *
	 * @since    9.3
	 * @param    object     $cart    		  	  Cart data
	 * @param    integer    $step_nr              Automation step number
	 * @param    boolean    $test                 Whether this is a test email or not
	 * @param    string     $email                Email that is used for sending a test email
	 * @param    array    	$preview_data         Automation step input data passed from frontend to allow template preview
	 */
	public function send_reminder( $cart, $step_nr, $test = false, $email = false, $preview_data = array() ){
		$admin = $this->admin();
		$automation = $this->automation();
		$settings = $this->get_settings();

		if($test){
			$to = $email;
			$language = get_locale();

		}else{
			$to = $cart->email;
			$language = $cart->language;
		}

		$admin->set_message_language( $language );
		$automation_steps = get_option('cartbounty_pro_automation_steps');
		$step = $automation_steps[$step_nr];

		if($test){
			$step = $preview_data;
		}

		$email_subject = $automation->get_content_input_fields( $step_nr, $step, 'subject', 'wordpress' );
		$subject = apply_filters( 'wpml_translate_single_string', $email_subject['value'], 'woo-save-abandoned-carts', $email_subject['name'] );
		$subject = html_entity_decode( $subject ); //If subject field includes encoded emojis - must decode them

		$message = $this->get_reminder_contents( $cart, $step_nr, $test, $preview_data, $subject );
		$from_name = ( !empty( $settings['from_name'] ) ) ? $settings['from_name'] : get_option( 'blogname' );
		$from_email = ( !empty( $settings['from_email'] ) ) ? $settings['from_email'] : get_option( 'admin_email' );
		$reply_to = $settings['reply_email'];
		$bcc = apply_filters( 'cartbounty_pro_wordpress_recovery_email_bcc', '' );

		$header = array(
			'from' 			=> 'From: ' . sanitize_text_field( stripslashes( $from_name ) ) . ' <' . sanitize_email( $from_email ) . '>',
			'content-type'	=> 'Content-Type: text/html; charset="' . esc_attr( get_option( 'blog_charset' ) ) . '"'
		);

		if( $reply_to ){
			$header['reply-to'] = 'Reply-To: <'. sanitize_email( $reply_to )  .'>';
		}

		if( !empty( $bcc ) ){ //Add bcc email address in case it is not empty
			$header['bcc'] = 'Bcc: ' . esc_html( $bcc );
		}

		$result = wp_mail( sanitize_email( $to ), $message['email_subject'], $message['content'], $header );

		if($result){ //In case if the email was successfully sent out
			if(!$test){ //If this is not a test email
				$current_time = current_time( 'mysql', true );
				$template = ( isset($step['template']) ) ? $step['template'] : $this->get_defaults( 'template', $step_nr );
				$automation->update_cart( $cart, $current_time, 'wordpress' ); //Update cart information
				$this->add_email( $cart->id, $template, $step_nr, $current_time ); //Create a new row in the emails table
			}

		}else{ //Log error in case email was not sent
			$admin->log( 'notice', sprintf( 'WordPress: Unable to send reminder email to %s', esc_html( $to ) ) );
			$admin->exclude_cart( 'wordpress', $cart ); //Exclude cart from further recovery
		}
		restore_previous_locale();
	}

	/**
	* Send a test email. 
	* If email field is empty, send email to default Administrator email
	*
	* @since    9.3
	* @return   HTML
	*/
	public function send_test(){
		if ( check_ajax_referer( 'test_email', 'nonce', false ) == false ) { //If the request does not include our nonce security check, stop executing function
			wp_send_json_error(esc_html__( 'Looks like you are not allowed to do this.', 'woo-save-abandoned-carts' ));
		}
		$step_nr = false;
		if(isset($_POST['step'])){
			$step_nr = $_POST['step'];
		}
		$preview_data = array();
		if(isset($_POST)){
			$preview_data = $this->get_preview_data($_POST);
		}

		$email = false;
		$direction = is_rtl() ? 'rtl' : 'ltr';

		if(isset($_POST['email'])){ //If we have received email field
			if(!empty($_POST['email'])){ //If email field is not empty
				if(is_email($_POST['email'])){ //If email is valid
					$email = $_POST['email'];
				}else{ //If email is invalid
					wp_send_json_error('<span class="license-status license-inactive fadeOutSlow" dir="'. $direction .'"><i class="license-status-icon"><img src="'. esc_url( plugin_dir_url( __DIR__ ) ) . 'admin/assets/invalid-icon.svg" /></i>'. esc_html__( 'Please enter a valid email', 'woo-save-abandoned-carts' ) .'</span>');
				}
			}else{ //If email input field is empty, sending it to default Administrator email
				$email = get_option( 'admin_email' );
			}
		}
		$this->send_reminder( $cart = false, $step_nr, $test = true, $email, $preview_data );
		wp_send_json_success('<span class="license-status license-active fadeOutSlow" dir="'. $direction .'"><i class="license-status-icon"><img src="'. esc_url( plugin_dir_url( __DIR__ ) ) . 'admin/assets/active-icon.svg" /></i>'. esc_html__( 'Email successfully sent', 'woo-save-abandoned-carts' ) .'</span>');
	}

	/**
	* Return email preview contents according to selected template and colors
	*
	* @since    9.3
	* @return   HTML
	*/
	public function email_preview(){
		if ( check_ajax_referer( 'preview_email', 'nonce', false ) == false ) { //If the request does not include our nonce security check, stop executing function
			wp_send_json_error(esc_html__( 'Looks like you are not allowed to do this.', 'woo-save-abandoned-carts' ));
		}

		$step_nr = false;

		if(isset($_POST['step'])){
			$step_nr = $_POST['step'];
		}

		$preview_data = array();

		if(isset($_POST)){
			$preview_data = $this->get_preview_data($_POST);
		}

		$contents = $this->get_reminder_contents( $cart = false, $step_nr, $test = true, $preview_data );
		wp_send_json_success( $contents['content'] );
	}

	/**
	* Retrieving input data that is used during email Preview and Testing
	*
	* @since    9.3
	* @return   array
	*/
	public function get_preview_data( $data ){
		$include_image = false;
		if(isset($data['include_image'])){
			if($data['include_image'] == 'true'){
				$include_image = true;
			}
		}
		
		$preview_data = array(
			'subject' 				=> isset($data['subject']) ? $data['subject'] : '',
			'heading' 				=> isset($data['main_title']) ? $data['main_title'] : '',
			'content' 				=> isset($data['content']) ? $data['content'] : '',
			'template' 				=> isset($data['template']) ? $data['template'] : '',
			'main_color' 			=> isset($data['main_color']) ? $data['main_color'] : '',
			'button_color'			=> isset($data['button_color']) ? $data['button_color'] : '',
			'text_color' 			=> isset($data['text_color']) ? $data['text_color'] : '',
			'background_color' 		=> isset($data['background_color']) ? $data['background_color'] : '',
			'include_image' 		=> $include_image,
			'main_image' 			=> isset($data['main_image']) ? $data['main_image'] : '',
			'coupon_generate'		=> isset($data['coupon_generate']) ? $data['coupon_generate'] : '',
			'coupon_expiry'			=> isset($data['coupon_expiry']) ? $data['coupon_expiry'] : '',
			'coupon_description'	=> isset($data['coupon_description']) ? $data['coupon_description'] : '',
			'coupon_code'			=> isset($data['coupon_code']) ? trim( $data['coupon_code'] ) : '',
			'coupon_prefix'			=> isset($data['coupon_prefix']) ? $data['coupon_prefix'] : ''
		);

		return $preview_data;
	}

	/**
     * Building email reminder contents according to automation step template, colors and content
     *
     * @since    9.3
     * @return   array
     * @param    object     $cart    		  	  Cart data. If false, then we must output
     * @param    array      $step_nr              Automation step number
     * @param    boolean    $test                 Weather request triggered by Email test or preview function
     * @param    array    	$preview_data         Automation step input data passed from frontend to allow template preview
     * @param    string    	$email_subject        Email subject in order to allow GTranslate to translate it in one go alongisde other strings
     */
	private function get_reminder_contents( $cart, $step_nr, $test = false, $preview_data = array(), $email_subject = '' ){
		$result = $this->get_selected_template( $cart, $step_nr, $test, $preview_data, $email_subject );
		ob_start();
		echo $result['content'];
		$content = ob_get_contents();
		ob_end_clean();

		return array(
			'content' 		=> $content,
			'email_subject' => $result['email_subject'],
		);
	}

	/**
     * Retrieve appropriate template for the automation
     *
     * @since    9.3
     * @return   array
     * @param    object     $cart    		  	  Cart data. If false, then we must output
     * @param    array      $step_nr              Automation step number
     * @param    boolean    $test                 Weather request triggered by Email test or preview function
     * @param    array    	$preview_data         Automation step input data passed from frontend to allow template preview
     * @param    string    	$email_subject        Email subject in order to allow GTranslate to translate it in one go alongisde other strings
     */
	private function get_selected_template( $cart, $step_nr, $test = false, $preview_data = array(), $email_subject = '' ){
		$public = $this->public();
		$admin = $this->admin();
		$automation = $this->automation();
		$coupons = new CartBounty_Pro_Coupons();
		$coupon = $coupons->get_coupon( 'wordpress', 'cartbounty_pro_automation_steps', $step_nr, $cart ); //Coupon code creation
		$automation_steps = get_option('cartbounty_pro_automation_steps');
		$step = $automation_steps[$step_nr];
		$source_language = apply_filters( 'cartbounty_pro_gtranslate_source_language', 'en' );
		$target_language = '';

		if( $test ){ //In case we are generating Preview - replace saved option array with dynamically loaded data from the form
			$step = $preview_data;
			$coupon = $preview_data;
			$target_language = apply_filters( 'cartbounty_pro_gtranslate_target_language_preview', 'es' );
		}

		//Setting defaults
		$main_color = '#ffffff';
		$button_color = '#ff5e2d';
		$text_color = '#000000';
		$background_color = '#f2f2f2';
		$footer_color = '#353535';
		$border_color = '#e9e8e8';
		$template = 1;
		$include_image = false;
		$main_image = $public->get_plugin_url() . '/public/assets/email-header-image.png';
		$products = array();
		$recovery_link = $admin->get_landing_url();
		$unsubscribe_link = $admin->get_landing_url();
		$track_open_rate = '';
		$message_heading = $automation->get_content_input_fields( $step_nr, $step, 'heading', 'wordpress' );
		$heading = apply_filters( 'wpml_translate_single_string', $message_heading['value'], 'woo-save-abandoned-carts', $message_heading['name'] );
		$message_content = $automation->get_content_input_fields( $step_nr, $step, 'content', 'wordpress' );
		$content = apply_filters( 'wpml_translate_single_string', $message_content['value'], 'woo-save-abandoned-carts', $message_content['name'] );
		$coupon_code = '';
		$coupon_prefix = '';
		$coupon_expiry = false;
		$coupon_description = $coupons->get_defaults('coupon_description');

		if(isset($step['main_color'])){
			if(!empty($step['main_color'])){
				$main_color = $step['main_color'];
				$border_color = $main_color;
			}
		}
		if(isset($step['button_color'])){
			if(!empty($step['button_color'])){
				$button_color = $step['button_color'];
			}
		}
		if(isset($step['text_color'])){
			if(!empty($step['text_color'])){
				$text_color = $step['text_color'];
			}
		}
		if(isset($step['background_color'])){
			if(!empty($step['background_color'])){
				$background_color = $step['background_color'];
				$footer_color = $public->invert_color($background_color);
			}
		}
		if(isset($step['template'])){
			if(!empty($step['template'])){
				$template = $step['template'];
			}
		}
		if(isset($step['include_image'])){
			if(!empty($step['include_image'])){
				$include_image = $step['include_image'];
			}
		}
		if(isset($step['main_image'])){
			if(!empty($step['main_image'])){
				$image_id = $step['main_image'];
				$image = wp_get_attachment_image_src( $image_id, 'full' );
				if(is_array($image)){
					$main_image = $image[0];
				}
			}
		}
		if(isset($coupon['coupon_code'])){
			if(!empty($coupon['coupon_code'])){
				$coupon_code = $admin->sanitize_field( stripslashes( $coupon['coupon_code']) );
			}
		}
		if(isset($coupon['coupon_expiry'])){
			if(!empty($coupon['coupon_expiry'])){
				$coupon_expiry = $admin->sanitize_field( stripslashes( $coupon['coupon_expiry']) );
			}
		}
		if(isset($coupon['coupon_description'])){
			if( !empty($step['coupon_description']) ){ //If the value is not empty and does not contain only whitespaces
				$coupon_description = $coupon['coupon_description'];
			}
		}

		$store_location = new WC_Countries();
		$address_1 = array();
		$address_2 = array();
		
		//Support for WooCommerce versions prior 3.1.1 where method get_base_address didn't exist
		if(method_exists($store_location, 'get_base_address')){
			if($store_location->get_base_address()){
				$address_1[] = $store_location->get_base_address();
			}
			if($store_location->get_base_address_2()){
				$address_1[] = $store_location->get_base_address_2();
			}
		}
		if($store_location->get_base_city()){
			$address_1[] = $store_location->get_base_city();
		}
		if($store_location->get_base_state()){
			$address_2[] = $store_location->get_base_state();
		}
		if($store_location->get_base_postcode()){
			$address_2[] = $store_location->get_base_postcode();
		}
		if(WC()->countries->countries[$store_location->get_base_country()]){
			$address_2[] = WC()->countries->countries[$store_location->get_base_country()];
		}

		$store_address = array(
			'address_1' => implode(', ', $address_1),
			'address_2' => implode(', ', $address_2)
		);

		if($test){ //In case we are generating a Preview
			$products = array( //Creating default product array
				array(
					'title' => esc_html__( 'Product name', 'woo-save-abandoned-carts' ),
					'price' => esc_html__( 'Price', 'woo-save-abandoned-carts' ),
					'quantity' => 1,
					'image' => $public->get_plugin_url() . 'public/assets/email-product-image-1.png',
					'id' => ''
				),
				array(
					'title' => esc_html__( 'Product name', 'woo-save-abandoned-carts' ),
					'price' => esc_html__( 'Price', 'woo-save-abandoned-carts' ),
					'quantity' => 1,
					'image' => $public->get_plugin_url() . 'public/assets/email-product-image-2.png',
					'id' => ''
				),
				array(
					'title' => esc_html__( 'Product name', 'woo-save-abandoned-carts' ),
					'price' => esc_html__( 'Price', 'woo-save-abandoned-carts' ),
					'quantity' => 1,
					'image' => $public->get_plugin_url() . 'public/assets/email-product-image-3.png',
					'id' => ''
				)
			);

			if(isset($step['coupon_generate'])){ //Handle additional coupon code generation functions in case coupon generation enabled
				if(($step['coupon_generate']) == 'true'){
					if(isset($step['coupon_prefix'])){ //Get coupon prefix
						$coupon_prefix = $step['coupon_prefix'];
					}

					$coupon_code = $admin->sanitize_field($coupons->generate_coupon_code( 'wordpress', 'cartbounty_pro_automation_steps', $step_nr, $coupon_prefix ));

					if(isset($step['coupon_expiry'])){
						$coupon_expiry = $admin->sanitize_field($coupons->get_preview_coupon_expiration_date( $step['coupon_expiry'] ));
					}

				}else{

					if( isset( $step['coupon_code'] ) && !empty( $step['coupon_code'] ) ){ //If coupon code selected, get date of the predefined coupon code
						$coupon_expiry = $admin->sanitize_field( $coupons->get_coupon_expiration_date( $step['coupon_code'] ) );
					}
				}
			}
		}

		$max_products = 3; //Maximum products that will be displayed in the abandoned cart email

		if($template == 2){
			$template_name = 'cartbounty-pro-email-row-contents.php';
			$template_slug = 'rows';
		}elseif($template == 3){
			$template_name = 'cartbounty-pro-email-column-contents.php';
			$template_slug = 'columns';
			$max_products = 6;
		}else{
			$template_name = 'cartbounty-pro-email-light.php';
			$template_slug = 'light';
		}

		if( isset( $cart->cart_contents ) ){ //If we have a cart

			if(!empty($cart->cart_contents)){
				$cart_contents = $admin->get_saved_cart_contents( $cart->cart_contents );

				if(is_array($cart_contents)){
					$limit = 1;
					foreach ($cart_contents as $key => $item) { //Building product array
						
						if($limit > apply_filters( 'cartbounty_pro_automation_max_products', $max_products )){ //Once we have reached the maximum product count that can be displayed, stop adding new ones
							break;
						}

						$product_title = $item['product_title'];

						if( apply_filters( 'cartbounty_pro_automation_hide_product_attributes', false ) ){ //Hide product attributes if set to true
							$title_parts = explode( ':', $product_title, 2 );

							if( isset( $title_parts[0] ) ){
								$product_title = $title_parts[0];
							}
						}

						$image_url = $admin->get_product_thumbnail_url( $item );
						$product_price = $admin->get_product_price( $item );

						$products[] = array(
							'title' => $product_title,
							'price' => $admin->format_price( $product_price, esc_html($cart->currency)),
							'quantity' => $item['quantity'],
							'image' => $image_url,
							'id' => $item['product_id']
						);
						$limit++;
					}
				}
				
				$unsubscribe_link = apply_filters( 'cartbounty_pro_automation_unsubscribe_url', $admin->get_unsubscribe_url( $cart->email, $cart->session_id, $cart->id, 'wordpress' ), $step_nr, 'wordpress' );
				$track_open_rate = $this->get_track_open_rate_url( $cart->email, $cart->session_id, $cart->id, $step_nr );
				$recovery_link = apply_filters('cartbounty_pro_automation_recovery_url', $admin->create_cart_url( $cart->email, $cart->session_id, $cart->id, 'wordpress' ), $step_nr, 'wordpress' ); //Recovery link
			}
		}

		if( empty( $coupon_code ) ){ //In case the coupon code is empty - do not output description
			$coupon_description = '';
		}

		if( isset( $cart->language ) ){
			$target_language = $cart->language;
		}
		
		$args = apply_filters(
			'cartbounty_pro_wordpress_recovery_args',
			array(
				'products'				=> $products,
				'main_color'			=> $main_color,
				'button_color'			=> $button_color,
				'text_color'			=> $text_color,
				'background_color'		=> $background_color,
				'footer_color'			=> $footer_color,
				'border_color'			=> $border_color,
				'include_image'			=> $include_image,
				'main_image'			=> $main_image,
				'heading'				=> $admin->sanitize_field( stripslashes( $admin->prepare_tags( $heading, $cart, strtoupper($coupon_code), $coupon_expiry, $recovery_link, $unsubscribe_link, $in_tags = true ) ) ),
				'content'				=> $admin->sanitize_field( stripslashes( $admin->prepare_tags( $content, $cart, strtoupper($coupon_code), $coupon_expiry, $recovery_link, $unsubscribe_link, $in_tags = true ) ) ),
				'store_address'			=> $store_address,
				'recovery_link'			=> $recovery_link,
				'unsubscribe_link'		=> $unsubscribe_link,
				'track_open_rate'		=> $track_open_rate,
				'current_year'			=> date('Y'),
				'step_nr'				=> $step_nr + 1,
				'slug'					=> $template_slug,
				'test'					=> $test,
				'coupon_code'			=> strtoupper($coupon_code),
				'coupon_expiry'			=> $coupon_expiry,
				'coupon_expires_text'	=> esc_html__( 'Coupon expires:', 'woo-save-abandoned-carts' ),
				'coupon_description'	=> $admin->sanitize_field( stripslashes( $admin->prepare_tags( $coupon_description, $cart, strtoupper($coupon_code), $coupon_expiry, $recovery_link, $unsubscribe_link, $in_tags = true ) ) ),
				'complete_checkout'		=> esc_html__( 'Complete checkout', 'woo-save-abandoned-carts' ),
				'unsubscribe'			=> esc_html__( 'Unsubscribe', 'woo-save-abandoned-carts' ),
				'copyright'				=> esc_html__( 'Copyright', 'woo-save-abandoned-carts' ),
				'rights_reserved'		=> esc_html__( 'All rights reserved.', 'woo-save-abandoned-carts' ),
				'source_language'		=> $source_language, //Introduced for GTranslate
				'target_language'		=> $target_language, //Introduced for GTranslate
				'email_subject'			=> $admin->sanitize_field( stripslashes( $admin->prepare_tags( $email_subject, $cart, strtoupper($coupon_code), $coupon_expiry ) ) ), //Introduced for GTranslate
			)
		);

		ob_start();
		echo $public->get_template( $template_name, $args, false, plugin_dir_path( __FILE__ ) . '../templates/emails/');
		$content = ob_get_contents();
		ob_end_clean();
		
		return array(
			'content' 		=> $content,
			'email_subject' => $args['email_subject'],
		);
	}

	/**
     * Add new email to sent emails table
     *
     * @since    9.3
     * @param    integer    $cart_id   			Cart ID
     * @param    integer    $template           Automation template
     * @param    integer    $step_nr            Automation step number
     * @param    string     $current_time       Current time
     */
	public function add_email( $cart_id, $template, $step_nr, $current_time ){
		global $wpdb;
		$admin = $this->admin();
		$automation = $this->automation();

		//Making sure that the email table exists or is created
		if( !$admin->table_exists( 'email_table_exists' ) ){
			$this->create_email_table();
		}

		$email_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME_EMAILS;

		$data = array(
			'cart' 				=> $cart_id,
			'template' 			=> $template,
			'step' 				=> $step_nr,
			'time' 				=> $current_time,
		);
		$format = array(
			'%d',
			'%d',
			'%d',
			'%s',
		);
		$wpdb->insert($email_table, $data, $format);
		$automation->increase_message_stats( $step_nr, 'send', 'wordpress' );
	}

	/**
     * Returning WordPress automation defaults
     *
     * @since    9.3
     * @return   array or string
     * @param    string     $value    		  	  Value to return
     * @param    integer    $automation    		  Automation number
     */
	public function get_defaults( $value = false, $automation = false ){
		$defaults = array();
		switch ( $automation ) {
			case 0:

				$defaults = array(
					'name'			=> esc_html__( 'First email', 'woo-save-abandoned-carts' ),
					'subject'		=> esc_attr__( 'Forgot something? 🙈', 'woo-save-abandoned-carts' ),
					'subject_name'	=> 'WordPress: First email subject',
					'heading'		=> esc_attr__( 'Forgot to complete your purchase? 🙈', 'woo-save-abandoned-carts' ),
					'heading_name'	=> 'WordPress: First email heading',
					'content'		=> esc_attr__( 'We noticed that you placed some nice items in your cart. Would you like to complete your order?', 'woo-save-abandoned-carts' ),
					'content_name'	=> 'WordPress: First email content',
					'interval'		=> 300000,
					'template'		=> 1
				);

				break;

			case 1:

				$defaults = array(
					'name'			=> esc_html__( 'Second email', 'woo-save-abandoned-carts' ),
					'subject'		=> esc_attr__( 'Return to complete your checkout!', 'woo-save-abandoned-carts' ),
					'subject_name'	=> 'WordPress: Second email subject',
					'heading'		=> esc_attr__( 'Still thinking it over?', 'woo-save-abandoned-carts' ),
					'heading_name'	=> 'WordPress: Second email heading',
					'content'		=> esc_attr__( 'We are keeping items in your cart reserved for you, but do not wait too long or they will expire 😇.', 'woo-save-abandoned-carts' ),
					'content_name'	=> 'WordPress: Second email content',
					'interval'		=> 86400000,
					'template'		=> 1
				);
			
				break;

			case 2:

				$defaults = array(
					'name'			=> esc_html__( 'Third email', 'woo-save-abandoned-carts' ),
					'subject'		=> esc_attr__( 'Ready to finish your order?', 'woo-save-abandoned-carts' ),
					'subject_name'	=> 'WordPress: Third email subject',
					'heading'		=> esc_attr__( 'Secure your items before they are released', 'woo-save-abandoned-carts' ),
					'heading_name'	=> 'WordPress: Third email heading',
					'content'		=> esc_attr__( 'We are holding your cart for a little longer. Popular items can sell out quickly — finish your order now to secure them. Need help? Just reply and we will assist.', 'woo-save-abandoned-carts' ),
					'content_name'	=> 'WordPress: Third email content',
					'interval'		=> 172800000,
					'template'		=> 1
				);
			
				break;

			case 3:

				$defaults = array(
					'name'			=> esc_html__( 'Fourth email', 'woo-save-abandoned-carts' ),
					'subject'		=> esc_attr__( 'Your cart is about to expire! 🛒', 'woo-save-abandoned-carts' ),
					'subject_name'	=> 'WordPress: Fourth email subject',
					'heading'		=> esc_attr__( 'Last chance to save your cart! 🛒', 'woo-save-abandoned-carts' ),
					'heading_name'	=> 'WordPress: Fourth email heading',
					'content'		=> esc_attr__( 'Goodbyes are never easy, but this is our last reminder. Products in your shopping cart will expire unless you take them with you.', 'woo-save-abandoned-carts' ),
					'content_name'	=> 'WordPress: Fourth email content',
					'interval'		=> 345600000,
					'template'		=> 1
				);
			
				break;
		}

		if($value){ //If a single value should be returned
			if(isset($defaults[$value])){ //Checking if value exists
				$defaults = $defaults[$value];
			}
		}

		return $defaults;
	}

	/**
	 * Creating database table to save email history of emails delivered by WordPress automation
	 *
	 * @since    9.3
	 */
	public static function create_email_table(){
		global $wpdb;
		$admin = new CartBounty_Pro_Admin( CARTBOUNTY_PRO_PLUGIN_NAME_SLUG, CARTBOUNTY_PRO_VERSION_NUMBER );
		$email_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME_EMAILS;
		$charset_collate = $wpdb->get_charset_collate();
		$misc_settings = $admin->get_settings( 'misc_settings' );

		$sql = "CREATE TABLE $email_table (
			id BIGINT(20) NOT NULL AUTO_INCREMENT,
			cart BIGINT(20) NOT NULL,
			template INT(3) DEFAULT 0,
			step INT(3) DEFAULT 0,
			time DATETIME DEFAULT '0000-00-00 00:00:00',
			open TINYINT(1) DEFAULT 0,
			click TINYINT(1) DEFAULT 0,
			recovered TINYINT(1) DEFAULT 0,
			unsubscribed TINYINT(1) DEFAULT 0,
			PRIMARY KEY (id)
		) $charset_collate;";

		require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
		dbDelta( $sql );
		
		//Resets table Auto increment index to 1
		$sql = "ALTER TABLE $email_table AUTO_INCREMENT = 1";
		dbDelta( $sql );
		
		$misc_settings['email_table_exists'] = true;
		update_option( 'cartbounty_pro_misc_settings', $misc_settings ); //Updating status and telling that table has been created
		return;
	}

	/**
	* Method sanitizes "From" field
	*
	* @since    9.3.3
	*/
	public function sanitize_from_field(){

		if( !isset( $_POST['cartbounty_pro_automation_settings']['from_name'] ) ) return; //Exit in case the field is not present in the request

		$settings = $this->get_settings();
		$settings['from_name'] = sanitize_text_field( $_POST['cartbounty_pro_automation_settings']['from_name'] );
		update_option( 'cartbounty_pro_automation_settings', $settings );
	}

	/**
	* Get open rate tracking URL
	*
	* @since    9.4.3
	* @return   HTML
	* @param    string    $email    		  Cart email address
	* @param    string    $session_id         Cart session
	* @param    integer   $id         		  Cart ID
	* @param    integer   $step_nr            Automation step number
	*/
	public function get_track_open_rate_url( $email, $session_id, $id, $step_nr ){
		$hash = hash_hmac('sha256', $email . $session_id, CARTBOUNTY_PRO_ENCRYPTION_KEY) . '-' . $id . '-' . $step_nr;
		$url = site_url( '?cartbounty-pro-track-open=' ) . $hash;
		return '<img src="'. esc_url($url) .'" height="0" width="0"/>';
	}

	/**
	* Add email tracking
	*
	* @since    9.4.3
	*/
	public function track_email_open_rate(){
		global $wpdb;
		$label = 'cartbounty-pro-track-open';
		$admin = $this->admin();
		$automation = $this->automation();

		//Checking if GET argument is present in the link. If not, exit function
		if (empty( $_GET[ $label ] )){
			return;
		}
		
		//Processing GET parameter from the link
		$hash = sanitize_text_field($_GET[ $label ]); //Getting and sanitizing GET value from the link
		$parts = explode('-', $hash); //Splitting GET value into hash and ID
		$hash = $parts[0];
		$id = $parts[1];
		$step_nr = $parts[2];

		//Retrieve row from the abandoned cart table in order to check if hashes match
		$cart_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME;
		$row = $wpdb->get_row(
			$wpdb->prepare(
				"SELECT email, session_id
				FROM $cart_table
				WHERE id = %d AND
				(type = %d OR type = %d)",
				$id,
				$admin->get_cart_type('abandoned'),
				$admin->get_cart_type('recovered_pending')
			)
		);

		if(empty($row)){ //Exit function if no row found
			return;
		}

		//Checking if hashes match
		$row_hash = hash_hmac('sha256', $row->email . $row->session_id, CARTBOUNTY_PRO_ENCRYPTION_KEY); //Building encrypted hash from the row
		if(!hash_equals($hash, $row_hash)){ //If hashes do not match, exit function
			return;
		}

		$automation->handle_message_stats( 'open', $id, $step_nr, 'wordpress' );
	}
}