<?php
/**
 * The BulkGate class
 *
 * Used to define BulkGate text message related functions
 *
 *
 * @since      9.7
 * @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_BulkGate{

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

	/**
	 * The coupons manager responsible for handling coupons.
	 *
	 * @since    10.9
	 * @access   protected
	 * @var      CartBounty_Pro_Coupons    $coupons    Provides methods to create, apply, and manage discount coupons.
	 */
	protected $coupons = null;

	/**
	 * The API connector responsible for handling communication with external services.
	 *
	 * @since    10.9
	 * @access   protected
	 * @var      CartBounty_Pro_API_Connector    $api    Provides methods to send and receive data via API requests.
	 */
	protected $api = null;

	/**
	 * The API access credentials used to authenticate requests with the external service.
	 *
	 * @since    10.9
	 * @access   protected
	 * @var      array    $api_access    Contains authentication data such as API key, token, or other required parameters.
	 */
	protected $api_access = 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;
	}

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

		return $this->coupons;
	}

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

		return $this->api;
	}

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

		return $this->api_access;
	}

	/**
	 * Starting BulkGate message automation process
	 *
	 * @since    9.7
	 */
	public function auto_send(){
		$admin = $this->admin();
		$automation = $this->automation();

		if( !$admin->check_license() || !class_exists( 'WooCommerce' ) ) return;

		if( $automation->automation_enabled( 'bulkgate' ) ){
			$this->recover_carts();
		}
	}

	/**
	 * Method retrieves saved API credentials
	 *
	 * @since    9.7
	 * @return 	 Array
	 */
	public function get_api_access(){

		$api_access = array(
			'api_key' 	=> '',
			'api_id' 	=> '',
			'api_url' 	=> 'https://portal.bulkgate.com/api/1.0/advanced/',
		);

		$bulkgate_settings = get_option( 'cartbounty_pro_bulkgate_settings' );

		if( !empty( $bulkgate_settings ) ){
			$api_access['api_key'] = esc_attr( $bulkgate_settings['api_token'] ); //Retrieve BulkGate API token from database
			$api_access['api_id'] = esc_attr( $bulkgate_settings['api_id'] ); //Retrieve BulkGate API ID from database
		}

		return $api_access;
	}

	/**
	 * Method checks if API is valid
	 * Return True if API valid. Return False if not
	 *
	 * @since    9.7
	 * @return 	 Boolean
	 */
	public function api_valid(){
		$admin = $this->admin();
		$api = $this->api();
		$status = false;
		$api_access = $this->api_access();
		$api_key = $api_access['api_key'];
		$api_id = $api_access['api_id'];

		if( !empty( $api_key ) && !empty( $api_id ) ){ //If BulkGate API fields are not empty

			$current_fingerprint = $admin->get_key_fingerprint( $api_key, $api_id );
			$valid_fingerprint = $admin->get_cartbounty_transient( 'bulkgate_valid_fingerprint' ); //Last known valid fingerprint
			
			if( $valid_fingerprint === $current_fingerprint ){ //If API token and ID have not changed and were already validated before
				$status = true;

			}else{

				$invalid_fp = $admin->get_cartbounty_transient( 'bulkgate_invalid_fingerprint' ); //Last known invalid fingerprint

				if( $invalid_fp !== $current_fingerprint ){ //If API token or ID have changed
					$invalid_until = (int)$admin->get_cartbounty_transient( 'bulkgate_api_invalid_until' );

					if( $invalid_until && time() < $invalid_until && $invalid_fp === $current_fingerprint ){ //Exit and return false if credentials have already failed before and they have not changed
						return $status;
					}

					if( (int)$api->credentials_test( 'bulkgate', $api_access, $this ) ){ //In case we get a valid response from BulkGate
						$admin->set_cartbounty_transient( 'bulkgate_valid_fingerprint', $current_fingerprint, 60*60*48 ); //Cache valid API fingerprint for 48 hours
						$admin->delete_cartbounty_transient( 'bulkgate_api_times_failed' );
						$admin->delete_cartbounty_transient( 'bulkgate_api_invalid_until' );
						$admin->delete_cartbounty_transient( 'bulkgate_invalid_fingerprint' );
						$status = true;

					}else{ //If we have connection issues - try and save response to limit how many times we try to connect
						$fail_count = (int)$admin->get_cartbounty_transient( 'bulkgate_api_times_failed' );
						$fail_count++;
						$admin->set_cartbounty_transient( 'bulkgate_api_times_failed', $fail_count, 60*60 ); //Remember failures for 1 hour

						if( $fail_count >= 3 ){
							$admin->set_cartbounty_transient( 'bulkgate_api_invalid_until', time() + 60*15, 60*15 ); //Invalidate requests for 15 minutes
							$admin->set_cartbounty_transient( 'bulkgate_invalid_fingerprint', $current_fingerprint, 60*15 ); //Cache invalid API fingerprint for 15 minutes
							$admin->delete_cartbounty_transient( 'bulkgate_valid_fingerprint' );
						}
					}
				}
			}
		}

		return $status;
	}

	/**
	 * Method returns API status
	 *
	 * @since    9.7
	 * @return 	 Array
	 */
	public function api_status(){
		$admin = $this->admin();
		$api_access = $this->api_access();
		$api_key = $api_access['api_key'];
		$api_id = $api_access['api_id'];
		$response = array();

		if( !empty( $api_key ) && !empty( $api_id ) ){ //If the fields are not empty
			
			if( $this->api_valid() ){
				$response['status'] = '1';
				$response['result'] = '';
				$response['message'] =  esc_html__( 'Connected', 'woo-save-abandoned-carts' );

			}else{
				$response['status'] = '0';
				$response['result'] = esc_html__( 'Error', 'woo-save-abandoned-carts' );
				$response['message'] =  esc_html__( 'Please make sure your API details are correct', 'woo-save-abandoned-carts' );
			}

		}else{ //In case API fields are empty
			$response['status'] = '0';
			$response['result'] = '';
			$response['message'] = '';
			$admin->delete_cartbounty_transient( 'bulkgate_api_times_failed' );
			$admin->delete_cartbounty_transient( 'bulkgate_api_invalid_until' );
			$admin->delete_cartbounty_transient( 'bulkgate_valid_fingerprint' );
			$admin->delete_cartbounty_transient( 'bulkgate_invalid_fingerprint' );
		}

		return $response;
	}

	/**
	 * Starting abandoned cart recovery
	 * Each batch does not send out more than 6 abandoned cart reminder messages (2 for each step)
	 * Before sending out the message we validate that the user has provided phone consent, has not unsubscribed, has a valid phone number, is in the allowed country and is out of quiet hours
	 *
	 * @since    9.7
	 */
	private function recover_carts(){
		global $wpdb;
		$admin = $this->admin();
		$automation = $this->automation();

		if( !$admin->tcpa_gdpr_confirmed( 'bulkgate' ) ) return; //Stop message sending in case TCPA/GPDR requirements not complete

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

		if( $admin->get_consent_settings( 'phone' ) ){ //Check if phone consent enabled to query only carts with given phone number usage consent
			$phone_consent_query = 'AND phone_consent = 1';
		}

		//Retrieving all abandoned carts that are eligible for recovery and have a phone number
		//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, sms_steps_completed, sms_last_sent
				FROM {$cart_table}
				WHERE (type = %d OR type = %d) AND
				phone != '' AND
				cart_contents != '' AND
				paused != 1 AND
				sms_excluded != 1 AND
				sms_unsubscribed != 1 AND
				sms_complete != 1 AND
				anonymized != 1 AND
				time < %s AND
				time > %s
				$phone_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( 'bulkgate' );
		$automation_steps = get_option( 'cartbounty_pro_bulkgate_steps' );
		$count = 0;

		foreach ( $active_steps as $key => $step ){ //Looping through active steps
			$automation_step = $automation_steps[$step];
			
			foreach ( $carts as $cart_key => $cart ){
				
				if( $cart->sms_steps_completed == $key ){ //If current step must be complete
					$first_step = false;
					$time = $cart->sms_last_sent;
					
					if( $cart->sms_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['sms_step_send_period'] ){ //Check if time has passed for current step

						if( $admin->is_valid_phone( $cart->phone, $cart->location ) ){ //If phone number is valid

							if( $admin->is_country_allowed_text_message( 'bulkgate', $cart ) ){ //If phone number is in the allowed country list
								
								if( $admin->quiet_hours_over( 'bulkgate', $cart ) ){
									
									if( !$admin->has_excluded_items( $cart, 'bulkgate' ) ){ //If cart contents do not have excluded items
										$this->send_reminder( $cart, $key ); //Must prepare and send out reminder message
										$count++;

										if( $count >= 2 ){
											$count = 0;
											break;
										}

									}else{
										$admin->exclude_cart( 'bulkgate', $cart ); //Exclude cart from further recovery
									}

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

							}else{ //If country excluded from messages - exclude message from further automations
								$admin->exclude_cart( 'bulkgate', $cart ); //Exclude cart from further recovery
							}

						}else{ //If phone number is not valid
							$admin->exclude_cart( 'bulkgate', $cart ); //Exclude cart from further recovery
						}
					}
				}
			}
		}
	}

	/**
	 * Send text message reminder
	 * Send out text messages according contents
	 * Create a new row in text message table
	 * Update abandoned cart last text message sent time, completed steps and if the automation is completed or not
	 *
	 * @since    9.7
	 * @return   boolean or array with error
	 * @param    object     $cart    		  	  Cart data
	 * @param    integer    $step_nr              Automation step number
	 * @param    boolean    $test                 Whether this is a test message or not
	 * @param    string     $phone                Phone that is used for sending test message
	 * @param    array    	$preview_data         Automation step input data passed from frontend
	 */
	public function send_reminder( $cart, $step_nr, $test = false, $phone = false, $preview_data = array() ){
		$admin = $this->admin();
		$automation = $this->automation();
		$api = $this->api();
		$result = true;
		$data = array();

		if( $test ){
			$to = $phone;
			$language = get_locale();
			$location = '';

		}else{
			$to = $cart->phone;
			$language = $cart->language;
			$location = $cart->location;
		}

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

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

		$message = $this->get_reminder_contents( $cart, $step_nr, $test, $preview_data );
		$message = html_entity_decode( $message ); //If message field includes encoded emojis - must decode them
		$sender_id = $this->get_selected_sender_type();
		$sender_id_value = $this->get_selected_sender_type_value();

		$data = array(
			'number' 			=> trim( $admin->prepare_phone_number( $to, $location ), '+' ),
			'text' 				=> $message,
			'duplicates_check' 	=> 'on'
		);

		if( !empty( $sender_id ) ){
			$data['sender_id'] = $sender_id['sender_id'];
		}

		if( !empty( $sender_id_value ) ){
			$data['sender_id_value'] = $sender_id_value;
		}

		if( $this->is_unicode( $message ) ){ //If contetns have unicode characters inside
			$data['unicode'] = apply_filters( 'cartbounty_pro_bulkgate_unicode', true );
		}

		$response = $api->connect( 'bulkgate', $this->api_access(), 'transactional', 'POST', $data );
		if( $response['status_code'] == 200 ){ //Successful
			
			if( !$test ){ //If this is not a test message
				$current_time = current_time( 'mysql', true );
				$automation->update_cart( $cart, $current_time, 'bulkgate' ); //Update cart information
				$this->add_text_message( $cart->id, $step_nr, $current_time ); //Create a new row in the sms message table
			}

		}else{ //Exclude the cart from further SMS message sync and log error in case message was not sent
			$admin->exclude_cart( 'bulkgate', $cart );
			$this->log_bkg_errors( 
				$response['response'],
				$extra = array(
					'phone' 	=> $to
				)
			);
			$result = array( $response['response'] );
		}

		restore_previous_locale();
		return $result;
	}

	/**
	* Send a test message 
	* If phone field is empty, do not send reminder message. Phone number is validated before sending out message
	*
	* @since    9.7
	* @return   HTML
	*/
	public function send_test(){
		
		if( check_ajax_referer( 'test_sms', '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' ) );
		}

		$admin = $this->admin();
		$direction = is_rtl() ? 'rtl' : 'ltr';
		$step_nr = false;

		if( isset( $_POST['step'] ) ){
			$step_nr = $_POST['step'];
		}
		$preview_data = array();
		
		if( isset( $_POST ) ){
			$preview_data = $this->get_preview_data( $_POST );
		}

		$phone = false;
		
		if(isset( $_POST['phone'] ) ){ //If we have received phone field
			
			if( !empty( $_POST['phone'] ) ){ //If phone field is not empty
				
				if( $admin->is_valid_phone( $_POST['phone'] ) ){ //If phone number is valid
					$phone = $_POST['phone'];

				}else{ //If phone 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 phone number', 'woo-save-abandoned-carts' ) .'</span>' );
				}

			}else{ //If phone input field is empty, sending it to default Administrator phone
				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 phone number', 'woo-save-abandoned-carts' ) .'</span>' );
			}
		}

		$result = $this->send_reminder( $cart = false, $step_nr, $test = true, $phone, $preview_data );
		
		if( !is_array( $result ) ){ //If no errors found
			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__( 'Message successfully sent', 'woo-save-abandoned-carts' ) .'</span>' );

		}else{ //If errors sending test message
			$error_object = $result[0];
			wp_send_json_success( '<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__( $error_object->error ) .'</span>' );
		}
		
	}

	/**
	* Retrieving input data that is used during message Testing
	*
	* @since    9.7
	* @return   array
	*/
	public function get_preview_data( $data ){		
		$preview_data = array(
			'content' 				=> isset( $data['content'] ) ? $data['content'] : '',
			'coupon_generate'		=> isset( $data['coupon_generate'] ) ? $data['coupon_generate'] : '',
			'coupon_code'			=> isset( $data['coupon_code'] ) ? $data['coupon_code'] : '',
			'coupon_expiry'			=> isset( $data['coupon_expiry'] ) ? $data['coupon_expiry'] : '',
			'coupon_prefix'			=> isset( $data['coupon_prefix'] ) ? $data['coupon_prefix'] : ''
		);

		return $preview_data;
	}

	/**
     * Building message reminder contents
     *
     * @since    9.7
     * @return   html
     * @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 message test function
     * @param    array    	$preview_data         Automation step input data passed from frontend to allow template preview
     */
	private function get_reminder_contents( $cart, $step_nr, $test = false, $preview_data = array() ){
		$admin = $this->admin();
		$coupons = $this->coupons();
		$automation = $this->automation();
		$coupon = $coupons->get_coupon( 'bulkgate', 'cartbounty_pro_bulkgate_steps', $step_nr, $cart ); //Coupon code creation
		$automation_steps = get_option( 'cartbounty_pro_bulkgate_steps' );
		$step = $automation_steps[$step_nr];
		$source_language = apply_filters( 'cartbounty_pro_gtranslate_source_language', 'en' );
		$target_language = '';

		if( $test ){ //In case we are dealing with Test message - 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
		$recovery_link = $admin->get_landing_url();
		$unsubscribe_link = $admin->get_landing_url();
		$message_contents = $automation->get_content_input_fields( $step_nr, $step, 'content', 'bulkgate' );
		$content = apply_filters( 'wpml_translate_single_string', $message_contents['value'], 'woo-save-abandoned-carts', $message_contents['name'] );
		$coupon_code = '';
		$coupon_prefix = '';
		$coupon_expiry = false;

		if( isset( $coupon['coupon_code'] ) ){
			
			if( !empty( $coupon['coupon_code'] ) ){
				$coupon_code = $admin->sanitize_field( stripslashes( $coupon['coupon_code']) );
			}
		}

		if( $test ){ //In case we are sending a test message
			
			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( 'bulkgate', 'cartbounty_pro_bulkgate_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'] ) ){ //If coupon code selected, get date of the predefined coupon code
						$coupon_expiry = $admin->sanitize_field( $coupons->get_coupon_expiration_date( $step['coupon_code'] ) );
					}
				}
			}
		}

		if( $cart ){ //If we have a cart - in case this is not a Test message
			$unsubscribe_link = apply_filters( 'cartbounty_pro_automation_unsubscribe_url', $admin->get_short_unsubscribe_url( $cart->phone, $cart->session_id, $cart->id, $step_nr ), $step_nr, 'bulkgate' );
			$recovery_link = apply_filters( 'cartbounty_pro_automation_recovery_url', $admin->create_short_cart_url( $cart->phone, $cart->session_id, $cart->id, 'bulkgate' ), $step_nr, 'bulkgate' ); //Recovery link
		}
		
		$content = $admin->sanitize_field( stripslashes( $admin->prepare_tags( $content, $cart, strtoupper( $coupon_code ), $coupon_expiry, $recovery_link, $unsubscribe_link, $in_tags = false ) ) );
		$content = htmlspecialchars_decode( $content ); //Making sure that special  HTML characters like &amp; are converted to &

		if( isset( $cart->language ) ){
			$target_language = $cart->language;
		}

		$payload = apply_filters(
			'cartbounty_pro_bulkgate_recovery_args',
			array(	
				'content' 				=> $content,
				'source_language'		=> $source_language, //Introduced for GTranslate
				'target_language'		=> $target_language, //Introduced for GTranslate
			)
		);

		return $payload['content'];
	}

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

		//Making sure that message table exists or is created
		if( !$admin->table_exists( 'message_table_exists' ) ){
			$this->create_message_table();
		}

		$message_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME_MESSAGES;

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

	/**
     * Returning automation defaults
     *
     * @since    9.7
     * @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 message', 'woo-save-abandoned-carts' ),
					'content'		=> sprintf(
										/* translators: %s - placeholders for specific content or links */
										esc_attr__( '%s: You placed some nice items in your cart. Complete your order here: %s. Unsubscribe here: %s', 'woo-save-abandoned-carts'), '[store_name]', '[recovery_link]', '[unsubscribe_link]' ),
					'content_name'	=> 'BulkGate: First message',
					'interval'		=> 300000
				);

				break;

			case 1:

				$defaults = array(
					'name'			=> esc_html__( 'Second message', 'woo-save-abandoned-carts' ),
					'content'		=> sprintf(
										/* translators: %s - placeholders for specific content or links */
										esc_attr__( '%s: Hi [name | friend]. Items in your cart may sell out! Complete your order now: %s. Unsubscribe here: %s', 'woo-save-abandoned-carts'), '[store_name]', '[recovery_link]', '[unsubscribe_link]' ),
					'content_name'	=> 'BulkGate: Second message',
					'interval'		=> 86400000
				);
			
				break;

			case 2:

				$defaults = array(
					'name'			=> esc_html__( 'Third message', 'woo-save-abandoned-carts' ),
					'content'		=> sprintf(
										/* translators: %s - placeholders for specific content or links */
										esc_attr__( '%s: Your cart is still reserved - return and claim your items: %s. Unsubscribe here: %s', 'woo-save-abandoned-carts'), '[store_name]', '[recovery_link]', '[unsubscribe_link]' ),
					'content_name'	=> 'BulkGate: Third message',
					'interval'		=> 172800000
				);
			
				break;

			case 3:

				$defaults = array(
					'name'			=> esc_html__( 'Fourth message', 'woo-save-abandoned-carts' ),
					'content'		=> sprintf(
										/* translators: %s - placeholders for specific content or links */
										esc_attr__( '%s: Your cart is about to expire! Complete your order here: %s. Unsubscribe here: %s', 'woo-save-abandoned-carts'), '[store_name]', '[recovery_link]', '[unsubscribe_link]' ),
					'content_name'	=> 'BulkGate: Fourth message',
					'interval'		=> 345600000
				);
			
				break;
		}

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

		return $defaults;
	}

	/**
     * Method displays available BulkGate sender types
     *
     * @since    9.7
     * @return   string
     */
	function display_sender_types(){
		$admin = $this->admin();
		$active_sender_type = $this->get_selected_sender_type();

		$sender_types = array();
		$sender_types['gSystem'] 	= esc_html__( 'System number', 'woo-save-abandoned-carts' );
		$sender_types['gText'] 		= esc_html__( 'Text sender', 'woo-save-abandoned-carts' );
		$sender_types['gOwn'] 		= esc_html__( 'Own phone number', 'woo-save-abandoned-carts' );
		$sender_types['gProfile'] 	= esc_html__( 'Sender ID profile', 'woo-save-abandoned-carts' );
		$sender_types['gMobile'] 	= esc_html__( 'Mobile Connect', 'woo-save-abandoned-carts' );

		echo '<select id="cartbounty-pro-automation-sender-id" class="cartbounty-pro-select" name="cartbounty_pro_bulkgate_settings[sender_id]" autocomplete="off" '. $admin->disable_field() .'>';
		foreach( $sender_types as $key => $type ){
			echo "<option value='". esc_attr( $key ) ."' ". selected( $active_sender_type['sender_id'], $key, false ) .">". esc_html( $type ) ."</option>";
		}
		echo '</select>';
	}

	/**
     * Method displays available BulkGate sender type name fields (conditionally depending on what was selected in the sender type dropdown field)
     *
     * @since    9.7
     * @return   string
     */
	function display_sender_names(){
		$admin = $this->admin();
		$bulkgate_settings = get_option( 'cartbounty_pro_bulkgate_settings' );
		$active_sender_type = $this->get_selected_sender_type();

		$sender_names = array(
			'gText' 	=> array(
				'name' 			=> esc_html__( 'Text sender name', 'woo-save-abandoned-carts' ),
				'description' 	=> esc_html__( 'Allows you to use a unique text for example a company name that appears instead of a phone number (e.g., MyShop.com, Amazon.com). The maximum number of characters is 11.', 'woo-save-abandoned-carts' )
			),
			'gOwn' 		=> array(
				'name' 			=> esc_html__( 'Phone number', 'woo-save-abandoned-carts' ),
				'description' 	=> esc_html__( 'Allows you to use your own phone number which is subsequently displayed in the delivered SMS. Recipient can text you or call you directly on this number. Requires number verification on BulkGate.', 'woo-save-abandoned-carts' )
			),
			'gProfile' 	=> array(
				'name' 			=> esc_html__( 'Profile ID', 'woo-save-abandoned-carts' ),
				'description' 	=> sprintf(
				/* translators: %s - URL link */
				esc_html__( '%sSender ID profile%s enables you to set up sender type for each country separately in one profile. This function is especially useful when creating and sending international SMS campaigns.', 'woo-save-abandoned-carts' ), '<a href="'. esc_url( CARTBOUNTY_PRO_BULKGATE_SENDER_ID_PROFILE_LINK ) .'" target="_blank">', '</a>' )
			),
			'gMobile' 	=> array(
				'name' 			=> esc_html__( 'Mobile connect key', 'woo-save-abandoned-carts' ),
				'description' 	=> sprintf(
				/* translators: %s - URL link */
				esc_html__( '%sMobile Connect%s is a mobile application for Android that allows you to connect your phone to BulkGate and use your mobile phone plan in the business communication with your customers.', 'woo-save-abandoned-carts' ), '<a href="'. esc_url( CARTBOUNTY_PRO_BULKGATE_SENDER_ID_MOBILE_CONNECT_LINK ) .'" target="_blank">', '</a>' )
			)
		);

		foreach( $sender_names as $key => $name ){
			$hidden_class = ' cartbounty-pro-hidden';
			$maxlength = '';

			if( $active_sender_type['sender_id'] == $key ){
				$hidden_class = '';
			}

			if( $key == 'gText' ){
				$maxlength = 'maxlength = "11"';
			}

			echo '<div class="cartbounty-pro-settings-group cartbounty-pro-automation-sender-name cartbounty-pro-automation-sender-name-'. esc_attr( $key ) .' '. $hidden_class .'">';
				echo '<label for="cartbounty-pro-automation-sender-name-'. esc_attr( $key ) .'">'. esc_html( $name['name'] ) .'</label>';
				echo '<input id="cartbounty-pro-automation-sender-name-'. esc_attr( $key ) .'" class="cartbounty-pro-text" type="text" name="cartbounty_pro_bulkgate_settings[sender_name_'. esc_attr( $key ) .']" '. $maxlength .' value="'. esc_attr( stripslashes( ( isset( $bulkgate_settings["sender_name_". esc_attr( $key )] ) ) ? $bulkgate_settings["sender_name_". esc_attr( $key )] : "" ) ).'" '. $admin->disable_field() .' />';
				echo '<p class="cartbounty-pro-additional-information">'. $name['description'] .'</p>';
			echo '</div>';
		}
	}

	/**
     * Method returns selected BulkGate sender type
     *
     * @since    9.7
     * @return   Array
     */
	function get_selected_sender_type(){
		$bulkgate_settings = get_option( 'cartbounty_pro_bulkgate_settings' );
		$selected_sender_type = array(
			'sender_id' 		=> 'gSystem'
		);

		if( isset( $bulkgate_settings['sender_id'] ) ){ //Fallback to default sender type if this setting hasn't been set before
			$selected_sender_type = array(
				'sender_id' 	=> $bulkgate_settings['sender_id']
			);
		}

		return $selected_sender_type;
	}

	/**
     * Method returns selected BulkGate sender type value
     *
     * @since    9.7
     * @return   string
     */
	function get_selected_sender_type_value(){
		$bulkgate_settings = get_option( 'cartbounty_pro_bulkgate_settings' );
		$sender_id = $this->get_selected_sender_type();
		$selected_sender_type_value = '';

		if( isset( $bulkgate_settings['sender_name_' . esc_attr( $sender_id['sender_id'] )] ) ){
			$selected_sender_type_value = $bulkgate_settings['sender_name_' . esc_attr( $sender_id['sender_id'] )];
		}

		return $selected_sender_type_value;
	}

	/**
	 * Creating database table to save text message history of messages delivered by BulkGate automation
	 *
	 * @since    9.7
	 */
	public static function create_message_table(){
		global $wpdb;
		$admin = new CartBounty_Pro_Admin( CARTBOUNTY_PRO_PLUGIN_NAME_SLUG, CARTBOUNTY_PRO_VERSION_NUMBER );
		$message_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME_MESSAGES;
		$charset_collate = $wpdb->get_charset_collate();
		$misc_settings = $admin->get_settings( 'misc_settings' );

		$sql = "CREATE TABLE $message_table (
			id BIGINT(20) NOT NULL AUTO_INCREMENT,
			cart BIGINT(20) NOT NULL,
			step INT(3) DEFAULT 0,
			automation VARCHAR(20),
			time DATETIME DEFAULT '0000-00-00 00:00:00',
			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 $message_table AUTO_INCREMENT = 1";
		dbDelta( $sql );
		
		$misc_settings['message_table_exists'] = true;
		update_option( 'cartbounty_pro_misc_settings', $misc_settings ); //Updating status and telling that table has been created
		return;
	}

	/**
	* Function handles Bulkgate error logging
	*
	* @since    9.7
	* @param 	object    $error - Bulkgate error
	* @param 	array     $extra - additional information to output, optional
	*/
	public function log_bkg_errors( $error, $extra = array() ){
		$admin = $this->admin();
		$additional_data = '';
		$error_code = '490';
		$error_message = 'Unknown error';

		if( isset( $extra['id'] ) ){
			$additional_data = 'Cart: ' . $extra['id'];
		}

		if( isset( $extra['phone'] ) ){
			$additional_data = 'Phone: ' . $extra['phone'];
		}

		if( !empty( $error->code ) ){
			$error_code = $error->code;
		}

		if( !empty( $error->error ) ){
			$error_message = $error->error;
		}

		$admin->log( 'notice', sprintf( 'BulkGate: %s - %s. %s', esc_html( $error_code ), esc_html( $error_message ), esc_html( $additional_data ) ) );
	}

	/**
     * Method returns information if unicode characters are in the message
     * Will return true for Arabic, Chinese, Russian, Latvian etc. languages
     *
     * @since    9.7.2.2
     * @return   Boolean
     */
	function is_unicode( $contents ){
		$unicode = false;
		
		if( strlen( $contents ) !== strlen( mb_convert_encoding( $contents, 'ISO-8859-1', 'UTF-8' ) ) ){
			$unicode = true;
		}

		return $unicode;
	}
}