<?php

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;

// Add commission table reference column edit screen link
add_filter( 'slicewp_list_table_commissions_column_reference', 'slicewp_list_table_commissions_add_reference_edit_link_edd', 10, 2 );
add_filter( 'slicewp_list_table_payout_commissions_column_reference', 'slicewp_list_table_commissions_add_reference_edit_link_edd', 10, 2 );

// Insert a new pending commission
add_action( 'edd_insert_payment', 'slicewp_insert_pending_commission_edd', 10, 2 );

// Checks whether the referring customer of the affiliate referrer is a new customer or not.
add_action( 'slicewp_referrer_affiliate_id_edd', 'slicewp_validate_referrer_affiliate_id_new_customer_edd', 15, 2 );

// Update the status of the commission to "unpaid", thus marking it as complete
add_action( 'edd_complete_purchase', 'slicewp_accept_pending_commission_edd', 10, 1 );

// Update the status of the commission to "rejected" when the originating purchase is refunded
add_action( 'edd_update_payment_status', 'slicewp_reject_commission_on_refund_edd', 10, 3 );

// Update the status of the commission to "rejected" when the originating purchase is deleted
add_action( 'edd_payment_delete', 'slicewp_reject_commission_on_delete_edd', 10 );

// Add the commission settings in download page
add_action( 'add_meta_boxes', 'slicewp_add_commission_settings_metabox_edd', 10, 2 );

// Saves the commissions settings in download meta
add_action( 'edd_save_download', 'slicewp_save_product_commission_settings_edd', 10, 2 );

// Add the commission settings in category page
add_action( 'download_category_add_form_fields', 'slicewp_add_category_commision_settings_edd', 10 );
add_action( 'download_category_edit_form_fields', 'slicewp_edit_category_commision_settings_edd', 10, 1 );

// Save the product category commission settings
add_action( 'create_download_category', 'slicewp_save_category_commission_settings_edd', 10, 3 );
add_action( 'edited_download_category', 'slicewp_save_category_commission_settings_edd', 10, 3 );

// Add the reference amount in the commission data
add_filter( 'slicewp_pre_insert_commission_data', 'slicewp_add_commission_data_reference_amount_edd' );
add_filter( 'slicewp_pre_update_commission_data', 'slicewp_add_commission_data_reference_amount_edd' );

// Add the EDD specific rewrite rules
add_action( 'init', 'slicewp_add_rewrite_rules_edd' );


/**
 * Adds the edit screen link to the reference column value from the commissions list table.
 *
 * @param string $output
 * @param array  $item
 *
 * @return string
 *
 */
function slicewp_list_table_commissions_add_reference_edit_link_edd( $output, $item ) {

	if ( empty( $item['reference'] ) ) {
		return $output;
	}

	if ( empty( $item['origin'] ) || $item['origin'] != 'edd' ) {
		return $output;
	}

    // Get the payment.
    $payment = edd_get_payment( $item['reference'] );

	// Create link to payment only if the payment exists.
    if ( ! empty( $payment->ID ) ) {
		$output = '<a href="' . esc_url( add_query_arg( array( 'post_type' => 'download', 'page' => 'edd-payment-history', 'view' => 'view-order-details', 'id' => $item['reference'] ), admin_url( 'edit.php' ) ) ) . '">' . $item['reference'] . '</a>';
	}

	return $output;

}


/**
 * Inserts a new pending commission when a new pending payment is registered
 *
 * @param int   $payment_id
 * @param array $payment_data
 *
 */
function slicewp_insert_pending_commission_edd( $payment_id, $payment_data ) {

	// Get and check to see if referrer exists.
	$affiliate_id = slicewp_get_referrer_affiliate_id();
	$visit_id	  = slicewp_get_referrer_visit_id();

	/**
	 * Filters the referrer affiliate ID for Easy Digital Downloads.
	 * This is mainly used by add-ons for different functionality.
	 *
	 * @param int $affiliate_id
	 * @param int $payment_id
	 *
	 */
	$affiliate_id = apply_filters( 'slicewp_referrer_affiliate_id_edd', $affiliate_id, $payment_id );

	if ( empty( $affiliate_id ) ) {
		return;
	}

	// Verify if the affiliate is valid
	if ( ! slicewp_is_affiliate_valid( $affiliate_id ) ){

		slicewp_add_log( 'EDD: Pending commission was not created because the affiliate is not valid.' );
		return;

	}

	// Check to see if the payment is a renewal or not.
	if ( function_exists( 'edd_get_order_meta' ) ) {
		$is_renewal = edd_get_order_meta( $payment_id, '_edd_sl_is_renewal', true );
	} else {
		$is_renewal = get_post_meta( $payment_id, '_edd_sl_is_renewal', true );
	}

	if ( ! empty( $is_renewal ) ) {

		slicewp_add_log( 'EDD: Pending commission was not created because the payment is a renewal.' );
		return;

	}

	// Check to see if a commission for this payment has been registered
	$commissions = slicewp_get_commissions( array( 'reference' => $payment_id, 'origin' => 'edd' ) );

	if ( ! empty( $commissions ) ) {

		slicewp_add_log( 'EDD: Pending commission was not created because another commission for the reference and origin already exists.' );
		return;

	}

	// Check to see if the affiliate made the purchase
	if ( empty( slicewp_get_setting( 'affiliate_own_commissions' ) ) ) {

		$affiliate = slicewp_get_affiliate( $affiliate_id );

		if ( is_user_logged_in() && get_current_user_id() == $affiliate->get('user_id') ) {

			slicewp_add_log( 'EDD: Pending commission was not created because the customer is also the affiliate.' );
			return;

		}
		
		if ( slicewp_affiliate_has_email( $affiliate_id, $payment_data['user_email'] ) ) {

			slicewp_add_log( 'EDD: Pending commission was not created because the customer is also the affiliate.' );
			return;

		}

	}


	// Process the customer
	$customer_args = array(
		'email'   	   => $payment_data['user_email'],
		'user_id' 	   => $payment_data['user_info']['id'],
		'first_name'   => $payment_data['user_info']['first_name'],
		'last_name'    => $payment_data['user_info']['last_name'],
		'affiliate_id' => $affiliate_id
	);

	$customer_id = slicewp_process_customer( $customer_args );

	if ( $customer_id ) {
		slicewp_add_log( sprintf( 'EDD: Customer #%s has been successfully processed.', $customer_id ) );
	} else {
		slicewp_add_log( 'EDD: Customer could not be processed due to an unexpected error.' );
	}


	// Get order.
	$order = ( function_exists( 'edd_get_order' ) ? edd_get_order( $payment_id ) : edd_get_payment( $payment_id ) );

	// Get formatted order data.
	$formatted_order_data = slicewp()->integrations['edd']->get_formatted_order_data( $order );

	// Set currencies.
	$active_currency = slicewp_get_setting( 'active_currency', 'USD' );
	$order_currency  = $formatted_order_data['currency'];

	// Prepare the transaction data.
	$transaction_data = $formatted_order_data;

	$transaction_data['original_currency'] = $transaction_data['currency'];
	$transaction_data['original_subtotal'] = $transaction_data['subtotal'];
	$transaction_data['original_total']    = $transaction_data['total'];
	$transaction_data['original_tax'] 	   = $transaction_data['tax'];

	$transaction_data['currency'] = $active_currency;
	$transaction_data['subtotal'] = slicewp_sanitize_amount( slicewp_maybe_convert_amount( $transaction_data['subtotal'], $order_currency, $active_currency ) );
	$transaction_data['total'] 	  = slicewp_sanitize_amount( slicewp_maybe_convert_amount( $transaction_data['total'], $order_currency, $active_currency ) );
	$transaction_data['tax'] 	  = slicewp_sanitize_amount( slicewp_maybe_convert_amount( $transaction_data['tax'], $order_currency, $active_currency ) );

	$transaction_data['customer_id'] = $customer_id;

	$transaction_data['currency_conversion_rate'] = slicewp_get_currency_conversion_rate( $order_currency, $active_currency );

	foreach ( $transaction_data['items'] as $key => $transaction_item_data ) {

		$transaction_item_data['original_subtotal'] = $transaction_item_data['subtotal'];
		$transaction_item_data['original_total']    = $transaction_item_data['total'];
		$transaction_item_data['original_tax'] 	    = $transaction_item_data['tax'];

		$transaction_item_data['subtotal'] = slicewp_sanitize_amount( slicewp_maybe_convert_amount( $transaction_item_data['subtotal'], $order_currency, $active_currency ) );
		$transaction_item_data['total']    = slicewp_sanitize_amount( slicewp_maybe_convert_amount( $transaction_item_data['total'], $order_currency, $active_currency ) );
		$transaction_item_data['tax'] 	   = slicewp_sanitize_amount( slicewp_maybe_convert_amount( $transaction_item_data['tax'], $order_currency, $active_currency ) );

		// Move meta_data at the end for cleaner array.
		if ( ! empty( $transaction_item_data['meta_data'] ) ) {
			$transaction_item_data = array_merge( array_diff_key( $transaction_item_data, array( 'meta_data' => $transaction_item_data['meta_data'] ) ), array( 'meta_data' => $transaction_item_data['meta_data'] ) );
		}

		$transaction_data['items'][$key] = $transaction_item_data;

	}

	// Move items at the end for cleaner array.
	if ( ! empty( $transaction_data['items'] ) ) {
		$transaction_data = array_merge( array_diff_key( $transaction_data, array( 'items' => $transaction_data['items'] ) ), array( 'items' => $transaction_data['items'] ) );
	}

	// Build the commission items for each item in the cart.
	$commission_amount 			   = 0;
	$commission_items 			   = array();
	$order_commission_types 	   = array();
	$is_commission_basis_per_order = slicewp_is_commission_basis_per_order();
	$cart_items 				   = edd_get_payment_meta_cart_details( $payment_id );

	if ( ! $is_commission_basis_per_order ) {

		// Commission items for product transaction items.
		foreach ( $transaction_data['items'] as $transaction_item_data ) {

			if ( $transaction_item_data['type'] != 'product' ) {
				continue;
			}

			// Get product, price and order item IDs.
			$product_id    = absint( $transaction_item_data['meta_data']['product_id'] );
			$price_id      = absint( $transaction_item_data['meta_data']['price_id'] );
			$order_item_id = absint( $transaction_item_data['meta_data']['order_item_id'] );

			// Get cart item.
			$cart_item = null;

			foreach ( $cart_items as $_cart_item ) {

				if ( empty( $_cart_item['order_item_id'] ) ) {
					continue;
				}

				if ( $order_item_id == $_cart_item['order_item_id'] ) {
					$cart_item = $_cart_item;
					break;
				}
				
			}

			// If we could not determine the cart item, continue to the next transaction item.
			if ( is_null( $cart_item ) ) {
				continue;
			}

			// Get the product categories.
            $categories = get_the_terms( $product_id, 'download_category' );

            // Verify if commissions are disabled for this product category.
            if ( ! empty( $categories[0]->term_id ) && get_term_meta( $categories[0]->term_id, 'slicewp_disable_commissions', true ) ) {
				continue;
			}

            // Verify if commissions are disabled for this product.
            if ( get_post_meta( $product_id, 'slicewp_disable_commissions', true ) ) {
				continue;
			}

			// Prepare commissionable amount.
			$commissionable_amount = $transaction_item_data['total'];

			// Exclude tax.
			if ( ! empty( slicewp_get_setting( 'exclude_tax', false ) ) ) {
				$commissionable_amount -= $transaction_item_data['tax'];
			}

			// Exclude Discounts Pro fees.
			if ( class_exists( 'edd_dp' ) ) {

				if ( ! empty( $price_id ) ) {
					$fee_key = 'dp_' . $product_id . '_' . $price_id;
				} else {
					$fee_key = 'dp_' . $product_id;
				}

				if ( ! empty( $cart_item['fees'][$fee_key]['amount'] ) ) {

					$commissionable_amount += slicewp_maybe_convert_amount( $cart_item['fees'][$fee_key]['amount'], $order_currency, $active_currency);

				} else {

					if ( function_exists( 'edd_get_order_adjustments' ) ) {

						$adjustments = edd_get_order_adjustments( array( 'object_id' => $order_item_id, 'object_type' => 'order_item', 'type' => 'fee', 'type_key' => $fee_key ) );

						if ( ! empty( $adjustments ) ) {

							$commissionable_amount += slicewp_maybe_convert_amount( $adjustments[0]->total, $order_currency, $active_currency );

						}

					}

				}

			}

			// Build commission item.
			$args = array(
				'origin'	   => 'edd',
				'type' 		   => ( ! empty( $cart_item['item_number']['options']['recurring'] ) ? 'subscription' : 'sale' ),
				'affiliate_id' => $affiliate_id,
				'product_id'   => $product_id,
				'quantity'	   => $transaction_item_data['quantity'],
				'customer_id'  => $customer_id
			);

			$commission_items[] = array(
				'commissionable_amount'   => slicewp_sanitize_amount( $commissionable_amount ),
				'commissionable_quantity' => $transaction_item_data['quantity'],
				'amount'				  => slicewp_sanitize_amount( slicewp_calculate_commission_amount( $commissionable_amount, $args ) ),
				'transaction_item'		  => $transaction_item_data
			);

            // Save the order commission types for future use.
            $order_commission_types[] = $args['type'];

		}

		// Sum up the commission items' amounts.
		if ( ! empty( $commission_items ) ) {
			$commission_amount = array_sum( array_column( $commission_items, 'amount' ) );
		}

	// Calculate the commission amount for the entire order.
	} else {

		$args = array(
			'origin'	   => 'edd',
			'type' 		   => 'sale',
			'affiliate_id' => $affiliate_id,
			'customer_id'  => $customer_id
		);

        $commission_amount = slicewp_calculate_commission_amount( 0, $args );
        
        // Save the order commission types for future use.
        $order_commission_types[] = $args['type'];

	}

    // Check that the commission amount is not zero.
    if ( ( $commission_amount == 0 ) && empty( slicewp_get_setting( 'zero_amount_commissions' ) ) ) {

        slicewp_add_log( 'EDD: Commission was not inserted because the commission amount is zero. Payment: ' . absint( $payment_id ) );
        return;

    }
    
    // Remove duplicated order commission types.
    $order_commission_types = array_unique( $order_commission_types );

	// Get the current referrer visit.
	$visit = slicewp_get_visit( $visit_id );

    // Prepare commission data.
	$commission_data = array(
		'affiliate_id'		=> $affiliate_id,
		'visit_id'			=> ( ! is_null( $visit ) && $visit->get( 'affiliate_id' ) == $affiliate_id ? $visit_id : 0 ),
		'type'				=> sizeof( $order_commission_types ) == 1 ? $order_commission_types[0] : 'sale',
		'status'			=> 'pending',
		'reference'			=> $payment_id,
		'reference_amount'	=> slicewp_sanitize_amount( $transaction_data['total'] ),
		'customer_id'		=> $customer_id,
		'origin'			=> 'edd',
		'amount'			=> slicewp_sanitize_amount( $commission_amount ),
		'currency'			=> $active_currency,
		'date_created'		=> slicewp_mysql_gmdate(),
		'date_modified'		=> slicewp_mysql_gmdate()
	);

	// Insert the commission.
	$commission_id = slicewp_insert_commission( $commission_data );

	if ( ! empty( $commission_id ) ) {

		// Add the transaction data as metadata.
		if ( ! empty( $transaction_data ) ) {

			slicewp_update_commission_meta( $commission_id, '__transaction_data', $transaction_data );

		}

		// Add commission items as metadata.
		if ( ! empty( $commission_items ) ) {

			slicewp_update_commission_meta( $commission_id, '__commission_items', $commission_items );

		}

		// Update the visit with the newly inserted commission_id if the visit isn't already marked as converted and
		// if the current referrer affiliate is the same as the visit's affiliate.
		if ( ! is_null( $visit ) ) {

			if ( $visit->get( 'affiliate_id' ) == $affiliate_id && empty( $visit->get( 'commission_id' ) ) ) {

				slicewp_update_visit( $visit_id, array( 'date_modified' => slicewp_mysql_gmdate(), 'commission_id' => $commission_id ) );

			}
			
		}
		
		slicewp_add_log( sprintf( 'EDD: Pending commission #%s has been successfully inserted.', $commission_id ) );
		
	} else {

		slicewp_add_log( 'EDD: Pending commission could not be inserted due to an unexpected error.' );
		
	}

}


/**
 * Updates the status of the commission attached to a payment to "unpaid", thus marking it as complete.
 *
 * @param int $payment_id
 *
 */
function slicewp_accept_pending_commission_edd( $payment_id ) {

	// Check to see if a commission for this payment has been registered.
	$commissions = slicewp_get_commissions( array( 'number' => -1, 'reference' => $payment_id, 'origin' => 'edd', 'order' => 'ASC' ) );

	if ( empty( $commissions ) ) {
		return;
	}

	foreach ( $commissions as $commission ) {

		// Return if the commission has already been paid.
		if ( $commission->get( 'status' ) == 'paid' ) {
			continue;
		}

		// Prepare commission data.
		$commission_data = array(
			'date_modified' => slicewp_mysql_gmdate(),
			'status' 		=> 'unpaid'
		);

		// Update the commission.
		$updated = slicewp_update_commission( $commission->get( 'id' ), $commission_data );

		if ( false !== $updated ) {

			slicewp_add_log( sprintf( 'EDD: Pending commission #%s successfully marked as completed.', $commission->get( 'id' ) ) );

		} else {

			slicewp_add_log( sprintf( 'EDD: Pending commission #%s could not be completed due to an unexpected error.', $commission->get( 'id' ) ) );

		}

	}

}


/**
 * Update the status of the commission to "rejected" when the originating purchase is refunded.
 *
 * @param int    $payment_id
 * @param string $new_status
 * @param string $old_status
 *
 */
function slicewp_reject_commission_on_refund_edd( $payment_id, $new_status, $old_status ) {

	if ( ! slicewp_get_setting( 'reject_commissions_on_refund', false ) ) {
		return;
	}

	if ( $new_status != 'refunded' ) {
		return;
	}

	// Check to see if a commission for this payment has been registered.
	$commissions = slicewp_get_commissions( array( 'number' => -1, 'reference' => $payment_id, 'origin' => 'edd', 'order' => 'ASC' ) );

	if ( empty( $commissions ) ) {
		return;
	}

	foreach ( $commissions as $commission ) {

		if ( $commission->get( 'status' ) == 'paid' ) {

			slicewp_add_log( sprintf( 'EDD: Commission #%s could not be rejected because it was already paid.', $commission->get( 'id' ) ) );
			continue;
	
		}

		// Add rejection reason for the commission.
		// We are adding the rejection reason early because the email notification is sent upon commission update.
		// If we'd update the rejection reason after updating the commission, the reason would not be available when sending the commission.
		// It would be great if we could update metadata on the fly alongside the object data and have all data available for the object update action.
		slicewp_update_commission_meta( $commission->get( 'id' ), '_rejection_reason', sprintf( __( "This commission has been rejected because the reference order #%s was refunded.", 'slicewp' ), $payment_id ) );
	
		// Prepare commission data.
		$commission_data = array(
			'date_modified' => slicewp_mysql_gmdate(),
			'status' 		=> 'rejected'
		);
	
		// Update the commission.
		$updated = slicewp_update_commission( $commission->get( 'id' ), $commission_data );
	
		if ( false !== $updated ) {

			slicewp_add_log( sprintf( 'EDD: Commission #%s successfully marked as rejected, after payment #%s was refunded.', $commission->get( 'id' ), $payment_id ) );

		} else {

			slicewp_add_log( sprintf( 'EDD: Commission #%s could not be rejected due to an unexpected error.', $commission->get( 'id' ) ) );

		}

	}

}


/**
 * Update the status of the commission to "rejected" when the originating purchase is deleted.
 *
 * @param int $payment_id
 *
 */
function slicewp_reject_commission_on_delete_edd( $payment_id ) {

	// Check to see if a commission for this payment has been registered.
	$commissions = slicewp_get_commissions( array( 'number' => -1, 'reference' => $payment_id, 'origin' => 'edd', 'order' => 'ASC' ) );

	if ( empty( $commissions ) ) {
		return;
	}

	foreach ( $commissions as $commission ) {

		if ( $commission->get( 'status' ) == 'paid' ) {

			slicewp_add_log( sprintf( 'EDD: Commission #%s could not be rejected because it was already paid.', $commission->get( 'id' ) ) );
			continue;
	
		}
	
		// Prepare commission data.
		$commission_data = array(
			'date_modified' => slicewp_mysql_gmdate(),
			'status' 		=> 'rejected'
		);
	
		// Update the commission.
		$updated = slicewp_update_commission( $commission->get( 'id' ), $commission_data );
	
		if ( false !== $updated ) {

			slicewp_add_log( sprintf( 'EDD: Commission #%s successfully marked as rejected, after payment #%s was deleted.', $commission->get( 'id' ), $payment_id ) );

		} else {

			slicewp_add_log( sprintf( 'EDD: Commission #%s could not be rejected due to an unexpected error.', $commission->get( 'id' ) ) );

		}

	}

}


/**
 * Adds the commissions settings metabox
 * 
 * @param string $post_type
 * @param WP_Post $post
 * 
 */
function slicewp_add_commission_settings_metabox_edd( $post_type, $post ) {

    // Check that post type is 'download'
    if ( $post_type != 'download' ) {
		return;
	}

    // Add the meta box
    add_meta_box( 'slicewp_metabox_commission_settings_edd', sprintf( __( '%1$s Commission Settings', 'slicewp' ), edd_get_label_singular(), edd_get_label_plural() ),  'slicewp_add_product_commission_settings_edd', $post_type, 'side', 'default' );

}


/**
 * Adds the product commission settings fields in EDD add/edit download page
 * 
 * 
 */
function slicewp_add_product_commission_settings_edd() {

    global $post;

    // Get the disable commissions value
    $disable_commissions = get_post_meta( $post->ID, 'slicewp_disable_commissions', true );

?>

    <div id="slicewp_product_settings" class="slicewp-options-groups-wrapper">

        <?php

            /**
             * Hook to add option groups before the core one
             * 
             */
            do_action( 'slicewp_edd_metabox_commission_settings_top' );

        ?>

        <div class="slicewp-options-group">

			<?php

				// Get the product categories
				$categories = get_the_terms( $post->ID, 'download_category' );

			?>

			<?php if ( ! empty( $categories[0]->term_id ) && get_term_meta( $categories[0]->term_id, 'slicewp_disable_commissions', true ) ): ?>

				<p class="slicewp-product-commissions-disabled"><?php echo __( 'The product commission rate settings are not available because the commissions for this product category are disabled.', 'slicewp' ); ?></p>

			<?php else: ?>

				<?php
					
					/**
					 * Hook to add settings before the core ones
					 * 
					 */
					do_action( 'slicewp_edd_metabox_commission_settings_core_top' );

				?>

				<p class="slicewp-option-field-wrapper">
					<label for="slicewp-disable-commissions">
						<input type="checkbox" class="slicewp-option-field-disable-commissions" name="slicewp_disable_commissions" id="slicewp-disable-commissions" value="1" <?php checked( $disable_commissions, true ); ?> />
						<?php echo sprintf( __( 'Disable commissions for this %s', 'slicewp' ), strtolower( edd_get_label_singular() ) ); ?>
					</label>
				</p>

				<?php

					/**
					 * Hook to add settings after the core ones
					 * 
					 */
					do_action( 'slicewp_edd_metabox_commission_settings_core_bottom' );
				?>

			<?php endif; ?>

        </div>

        <?php

            /**
             * Hook to add option groups after the core one
             * 
             */
            do_action( 'slicewp_edd_metabox_commission_settings_bottom' );
        
        ?>

    </div>

<?php

    // Add nonce field
    wp_nonce_field( 'slicewp_save_meta', 'slicewp_token', false );

}


/**
 * Saves the product commission settings into the product meta
 * 
 * @param int $post_id
 * @param WP_Post $post
 * 
 */
function slicewp_save_product_commission_settings_edd( $post_id, $post ) {

    // Verify for nonce
    if ( empty( $_POST['slicewp_token'] ) || ! wp_verify_nonce( $_POST['slicewp_token'], 'slicewp_save_meta' ) ) {
		return $post_id;
	}
    
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return $post_id;
	}

    if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
		return $post_id;
	}

    // Update the disable commissions settings
    if ( ! empty( $_POST['slicewp_disable_commissions'] ) ) {

        update_post_meta( $post_id, 'slicewp_disable_commissions', 1 );

    } else {

        delete_post_meta( $post_id, 'slicewp_disable_commissions' );

    }

}


/**
 * Adds the Category Rate and Type fields in the add new product category page
 * 
 */
function slicewp_add_category_commision_settings_edd() {

    /**
     * Hook to add fields before the core ones
     * 
     */
    do_action( 'slicewp_edd_add_category_form_fields_top' );
    
	?>

    <div class="slicewp-option-field-wrapper form-field">

        <label for="slicewp-disable-commissions">
            <input type="checkbox" class="slicewp-option-field-disable-commissions checkbox" name="slicewp_disable_commissions" id="slicewp-disable-commissions"/><?php echo __( 'Disable Commissions', 'slicewp' ); ?>
        </label>
        <p><?php echo __( 'When checked, commissions will not be generated for this product category.', 'slicewp' ); ?></p>

    </div>

	<?php

    /**
     * Hook to add fields after the core ones
     * 
     */
    do_action( 'slicewp_edd_add_category_form_fields_bottom' );

}


/**
 * Adds the disable commissions checkbox in the edit product category page
 * 
 * @param WP_Term $category
 * 
 */
function slicewp_edit_category_commision_settings_edd( $category ) {

    // Get the product category commission settings
    $current_category_disable_commissions = get_term_meta( $category->term_id, 'slicewp_disable_commissions', true );

    /**
     * Hook to add fields before the core ones
     * 
     */
    do_action( 'slicewp_edd_edit_category_form_fields_top', $category );
    
?>

    <tr class="slicewp-option-field-wrapper form-field">
        <th scope="row">
            <label for="slicewp-disable-commissions"><?php echo __( 'Disable Commissions', 'slicewp' ); ?></label>
        </th>
        <td>
            <input type="checkbox" class="slicewp-option-field-disable-commissions checkbox" name="slicewp_disable_commissions" id="slicewp-disable-commissions" <?php checked( $current_category_disable_commissions, true ); ?>/>
            <p class="description"><?php echo __( 'When checked, commissions will not be generated for this product category.', 'slicewp' ); ?></p>
        </td>
    </tr>

<?php

    /**
     * Hook to add fields after the core ones
     * 
     */
    do_action( 'slicewp_edd_edit_category_form_fields_bottom', $category );


}


/**
 * Saves the product category commission settings into the category meta
 * 
 * @param int $category_id
 * 
 */
function slicewp_save_category_commission_settings_edd( $category_id ) {

    // Update the disable commissions settings
    if ( ! empty( $_POST['slicewp_disable_commissions'] ) ) {

        update_term_meta( $category_id, 'slicewp_disable_commissions', 1 );
    
    } else {

        delete_term_meta( $category_id, 'slicewp_disable_commissions' );
    
    }

}


/**
 * Checks whether the referring customer of the affiliate referrer is a new customer or not.
 * If they are, the affiliate referrer is no longer valid.
 * 
 * @param int $affiliate_id
 * @param int $order_id
 * 
 * @return int
 * 
 */
function slicewp_validate_referrer_affiliate_id_new_customer_edd( $affiliate_id, $order_id ) {

	if ( empty( slicewp_get_setting( 'new_customer_commissions_only' ) ) ) {
		return $affiliate_id;
	}

	// Get current order.
	$order = edd_get_order( $order_id );

	if ( empty( $order ) ) {
		return $affiliate_id;
	}

	// Get customer's order count.
	if ( ! empty( $order->customer_id ) ) {
		$orders_count = edd_count_orders( array( 'customer_id' => $order->customer_id ) );
	} else {
		$orders_count = edd_count_orders( array( 'email' => $order->email ) );
	}

	return ( $orders_count > 1 ? 0 : $affiliate_id );

}


/**
 * Adds the reference amount in the commission data.
 * 
 * @todo - This should only be updated if the commission has no reference amount data already saved.
 * 
 * @param array $commission_data
 * 
 * @return array
 * 
 */
function slicewp_add_commission_data_reference_amount_edd( $commission_data ) {

	if ( ! ( doing_action( 'slicewp_admin_action_add_commission' ) || doing_action( 'slicewp_admin_action_update_commission' ) ) ) {
		return $commission_data;
	}

	// Check if the origin is Easy Digital Downloads.
	if ( 'edd' != $commission_data['origin'] ) {
		return $commission_data;
	}

	// Check if we have a reference.
	if ( empty( $commission_data['reference'] ) ) {
		return $commission_data;
	}

	// Get the payment.
	$payment = edd_get_payment( $commission_data['reference'] );

	if ( empty( $payment ) ) {
		return $commission_data;
	}

	// Save the reference amount.
	$commission_data['reference_amount'] = slicewp_sanitize_amount( $payment->total );

	// Return the updated commission data.
	return $commission_data;

}


/**
 * Add the rewrite rules for the 'downloads' category.
 * 
 */
function slicewp_add_rewrite_rules_edd() {

	// Get the affiliate keyword
	$keyword = slicewp_get_setting( 'affiliate_keyword' );

	// Get the 'downloads' post type
	$post_type = get_post_type_object( 'download' );

	// Get the rewrite slug
	$downloads_slug = ( ( is_array( $post_type->rewrite ) && ! empty( $post_type->rewrite['slug'] ) ) ? $post_type->rewrite['slug'] : 'downloads' );

	// Add the rewrite rule
	add_rewrite_rule( $downloads_slug . '/' . $keyword . '(/(.*))?/?$', 'index.php?post_type=' . $post_type->query_var . '&' . $keyword . '=$matches[2]', 'top' );

}


/**
 * Returns an array of products data from Easy Digital Downloads to populate the "slicewp_action_ajax_get_products" AJAX callback.
 * 
 * @param array $products
 * 
 * @return array
 * 
 */
function slicewp_action_ajax_get_products_edd( $products, $args = array() ) {

	if ( empty( $args['origin'] ) || $args['origin'] != 'edd' ) {
		return $products;
	}

	if ( empty( $args['search_term'] ) ) {
		return $products;
	}

	$downloads = get_posts( array(
		'post_type'      => 'download',
		'posts_per_page' => -1,
		'post_status'    => 'publish',
		's'				 => $args['search_term']
	));

	foreach ( $downloads as $download ) {

		$products[] = array(
			'origin' => 'edd',
			'id'   	 => $download->ID,
			'name'   => $download->post_title
		);

	}

	return $products;

}
add_filter( 'slicewp_action_ajax_get_products', 'slicewp_action_ajax_get_products_edd', 20, 2 );