<?php

/**
 * Class to define an Admin Table for showing subscribers of a giveaway
 */

if( ! defined( 'ABSPATH' ) ) {
	return;
}

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

class SG_Subscriber_Entries_Table extends WP_List_Table {

	/**
	 * Settings
	 *
	 * @var null|array
	 */
	public $settings = null;

	/**
	 * Form Fields
	 * @var null|array
	 */
	protected $subscriber = null;

	/**
     * Caching Subscriber Emails by Subscriber ID.
	 * @var array
	 */
	protected $subscriber_emails = array();

	/**
     * Action object.
     *
	 * @var null
	 */
	protected $action_object = null;

	/** Class constructor */
	public function __construct() {

		parent::__construct( array(
			'singular' => __( 'Entry', 'giveasap' ), //singular name of the listed records
			'plural'   => __( 'Entries', 'giveasap' ), //plural name of the listed records
			'ajax'     => false //should this table support ajax?
		));

		$this->_column_headers = $this->get_columns();
	}

	/**
	 * Get the settings
	 */
	public function get_settings() {
		if ( null === $this->settings ) {
			$this->settings = giveasap_get_settings();
		}

		return $this->settings;
	}

	/**
	 * Get the settings
	 */
	public function get_subscriber() {
		if ( null === $this->subscriber ) {
			$subscriber_id = isset( $_REQUEST['subscriber'] ) ? intval( $_REQUEST['subscriber'] ) : 0;
			if ( $subscriber_id ) {
				$this->subscriber = sg_get_subscriber( $subscriber_id );
			}
		}

		return $this->subscriber;
	}

	/**
     * Get the subscriber email from the cache or from DB
     *
	 * @param integer $subscriber_id
	 *
	 * @return string
	 */
	public function get_subscriber_email( $subscriber_id ) {

	    if ( ! isset( $this->subscriber_emails[ $subscriber_id ] ) ) {
		    $user = giveasap_get_user_by_id( $subscriber_id );
		    if ( ! $user ) {
		        return '-';
            }
		    $this->subscriber_emails[ $subscriber_id ] = $user->email;
        }

		return $this->subscriber_emails[ $subscriber_id ];
	}

	/**
	 * Retrieve user's data from the database
	 *
	 * @param int $per_page
	 * @param int $page_number
	 *
	 * @return mixed
	 */
	public static function get_entries( $per_page = 5, $page_number = 1 ) {

		global $wpdb;

		$subscriber_id = isset( $_REQUEST['subscriber'] ) ? intval( $_REQUEST['subscriber'] ) : 0;
        $giveaway_id   = isset( $_REQUEST['giveaway'] ) ? absint( $_REQUEST['giveaway'] ) : 0;
        $action_type   = isset( $_REQUEST['action_type'] ) ? $_REQUEST['action_type'] : '';

		$sql  = 'SELECT sg_entries.*, subscribers.email, giveaways.post_title as giveaway_title FROM ' . $wpdb->giveasap_actions . ' as sg_entries';
		$sql .= ' LEFT JOIN ' . $wpdb->giveasap_entries . ' as subscribers on subscribers.id=sg_entries.subscriber_id';
		$sql .= ' LEFT JOIN ' . $wpdb->posts . ' as giveaways on giveaways.ID=sg_entries.giveaway_id';

		$sql .= ' WHERE 1=1';

		if ( $subscriber_id ) {
			$sql .= $wpdb->prepare( ' AND sg_entries.subscriber_id = %d', $subscriber_id );
		}

		if ( $giveaway_id ) {
			$sql .= $wpdb->prepare( ' AND sg_entries.giveaway_id = %d', $giveaway_id );
		}

		if ( $action_type ) {
			$sql .= $wpdb->prepare( ' AND sg_entries.action = %s', $action_type );
        }

		if ( ! empty( $_REQUEST['orderby'] ) ) {
			$sql .= ' ORDER BY ' . esc_sql( $_REQUEST['orderby'] );
			$sql .= ! empty( $_REQUEST['order'] ) ? ' ' . esc_sql( $_REQUEST['order'] ) : ' ASC';
		}

		$sql .= ' LIMIT ' . $per_page;

		$sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;

        $result = $wpdb->get_results( $sql, 'ARRAY_A' );

		return $result;
	}

	/**
	 * Delete a user record.
	 *
	 * @param int $id customer ID
	 */
	public static function delete_action( $id ) {
		global $wpdb;

		$action = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->giveasap_actions WHERE id=%d", $id ), ARRAY_A );

		if ( ! $action ) {
		    return;
        }
		$ret = $wpdb->delete(
			$wpdb->giveasap_actions,
			array( 'id' => $id ),
			array( '%d' )
		);

		if ( false !== $ret ) {
            $subscriber = sg_get_subscriber( $action['subscriber_id'] );
            $subscriber->remove_entries( $action['entries'] );
		}
	}

	/**
	 * Returns the count of records in the database.
	 *
	 * @return null|string
	 */
	public static function record_count() {
		global $wpdb;

		$subscriber_id = isset( $_REQUEST['subscriber'] ) ? intval( $_REQUEST['subscriber'] ) : 0;
		$giveaway_id   = isset( $_REQUEST['giveaway'] ) ? absint( $_REQUEST['giveaway'] ) : 0;
		$action_type   = isset( $_REQUEST['action_type'] ) ? $_REQUEST['action_type'] : '';

		$sql = 'SELECT COUNT(*) FROM ' . $wpdb->giveasap_actions . ' as sg_entries';

		$sql .= ' WHERE 1=1';

		if ( $subscriber_id ) {
			$sql .= $wpdb->prepare( ' AND subscriber_id = %d', $subscriber_id );
		}

		if ( $giveaway_id ) {
			$sql .= $wpdb->prepare( ' AND giveaway_id = %d', $giveaway_id );
		}

		if ( $action_type ) {
			$sql .= $wpdb->prepare( ' AND action = %s', $action_type );
		}

        return $wpdb->get_var( $sql );
	}

	/** Text displayed when no user data is available */
	public function no_items() {
		_e( 'No Entries.', 'giveasap' );
	}

	/**
	 * Render a column when no column specific method exists.
	 *
	 * @param array $item
	 * @param string $column_name
	 *
	 * @return mixed
	 */
	public function column_default( $item, $column_name ) {
		return $item[ $column_name ];
	}

	/**
	 * Return the Giveaway
	 * @param $item
	 */
	public function column_giveaway( $item ) {
		return $item['giveaway_title'] ? $item['giveaway_title'] : get_the_title( $item['giveaway_id'] );
	}

	/**
	 * Actions for each subscriber.
	 *
	 * @param $item
	 *
	 * @return string
	 */
	public function column_actions( $item ) {
		$resend_nonce = wp_create_nonce( 'giveasap_delete_entry' );

		$subscriber_actions = array();
		$resend_args        = array(
			'post_type'    => 'giveasap',
			'page'         => esc_attr( $_REQUEST['page'] ),
			'action'       => 'delete_action_entry',
			'action_id'    => absint( $item['id'] ),
			'subscriber'   => absint( $item['subscriber_id'] ),
			'delete_nonce' => $resend_nonce,
			'paged'        => isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 1,
		);

		$delete_url = add_query_arg( $resend_args, admin_url( 'edit.php' ) );


		if ( isset( $_REQUEST['id'] ) ) {
			$resend_args['id'] = absint( $_REQUEST['id'] );
		}

		if ( 'completed' !== $item['status'] ) {
		    $resend_args['action'] = 'complete_action_entry';
			$complete_url = add_query_arg( $resend_args, admin_url( 'edit.php' ) );
			$subscriber_actions['complete'] = '<a class="button button-small sg-tooltip" href="' . esc_attr( $complete_url ) . '" title="' . __( 'Complete the Entry', 'giveasap' ) . '"><span class="fal fa-check"></span></a>';
		}

		if ( 'invalid' !== $item['status'] ) {
			$resend_args['action'] = 'invalid_action_entry';
			$complete_url = add_query_arg( $resend_args, admin_url( 'edit.php' ) );
			$subscriber_actions['invalid'] = '<a class="button button-small sg-tooltip" href="' . esc_attr( $complete_url ) . '" title="' . __( 'Invalidate the Entry', 'giveasap' ) . '"><span class="fal fa-ban"></span></a>';
		}

		$subscriber_actions['delete'] = '<a class="button button-small sg-button-red sg-tooltip" href="' . esc_attr( $delete_url ) . '" title="' . __( 'Delete the Entry', 'giveasap' ) . '"><span class="fal fa-trash"></span></a>';

		$subscriber_actions = apply_filters( 'sg_admin_subscriber_entries_actions_column', $subscriber_actions, $item );
		$html = '';
		if ( $subscriber_actions ) {
			$html = implode( ' ', $subscriber_actions );
		}
		return $html;
	}

	/**
	 * Render the bulk edit checkbox
	 *
	 * @param array $item
	 *
	 * @return string
	 */
	function column_cb( $item ) {
		return sprintf(
			'<input type="checkbox" name="bulk-delete[]" value="%s" />', $item['id']
		);
	}

	/**
     * Show the column email
     *
	 * @param array $item
	 */
	public function column_email( $item ) {

	    $email = $item['email'] ? $item['email'] : '-';

	    if ( $email ) {
		    $actions = array(
			    'entries' => sprintf( '<a href="edit.php?post_type=giveasap&page=%s&subscriber=%d">' . __( 'All Entries', 'giveasap' ) . '</a>', 'giveasap-subscriber-entries', absint( $item['subscriber_id'] ) ),
		    );

		    $email .= $this->row_actions( $actions );
	    }

		return $email;
    }

	/**
	 * Actions for each subscriber.
	 *
	 * @param $item
	 *
	 * @return string
	 */
	public function column_title( $item ) {
	    $data = maybe_unserialize( $item['data'] );

	    if ( isset( $data['title'] ) ) {
	        return $data['title'];
        }
	}

	/**
	 * @param $item
	 *
	 * @return string
	 */
	public function column_status( $item ) {
		return '<span class="sg-badge sg-entries-status sg-status sg-status-' . $item['status'] . '">' . $item['status'] . '</span>';
	}

	/**
	 * Actions for each subscriber.
	 *
	 * @param $item
	 *
	 * @return string
	 */
	public function column_value( $item ) {
	    $registered_actions = sg_get_registered_actions();
		if ( ! isset( $registered_actions[ $item['action'] ] ) ) {
		    return apply_filters( 'sg_extra_action_not_registered_column_value', '-', $item );
        }

		if ( ! class_exists( $registered_actions[ $item['action'] ] ) ) {
			return '-';
		}

		$action        = $registered_actions[ $item['action'] ];
		$action_object = new $action();
		$action_object->prepare_value_for_entries_table( $item );

		return $action_object->get_value_for_entries_table( maybe_unserialize( $item['data'] ) );
	}

	/**
	 *  Associative array of columns
	 *
	 * @return array
	 */
	public function get_columns() {
		$columns = array(
			//'cb'      => '<input type="checkbox" />',
			'email'   => __( 'Email', 'giveasap' ),
			'action'  => __( 'Action', 'giveasap' ),
			'title'   => __( 'Title', 'giveasap' ),
			'value'   => __( 'Value', 'giveasap' ),
			'entries' => __( 'Entries', 'giveasap' ),
            'status'  => __( 'Status', 'giveasap' ),
		);

		if ( null !== $this->get_subscriber() ) {
		    unset( $columns['email'] );
        }

		$giveaway_id = isset( $_GET['giveaway'] ) ? absint( $_GET['giveaway'] ) : 0;

		if ( ! $giveaway_id ) {
		    $columns['giveaway'] = __( 'Giveaway', 'giveasap' );
        }

		$columns['actions'] = __( 'Actions', 'giveasap' );

		return $columns;
	}

	/**
	 * Columns to make sortable.
	 *
	 * @return array
	 */
	public function get_sortable_columns() {
		$sortable_columns = array(
			'entries' => array( 'entries', true ),
            'email'   => array( 'email', true ),
		);

		return $sortable_columns;
	}

	/**
	 * Returns an associative array containing the bulk action
	 *
	 * @return array
	 */
	public function get_bulk_actions() {
		$actions = array(
			//'bulk-delete' => 'Delete'
		);

		return $actions;
	}

	/**
	 * Handles data query and filter, sorting, and pagination.
	 */
	public function prepare_items() {

		$columns = $this->get_columns();
		$hidden = array();
		$sortable = $this->get_sortable_columns();
		$this->_column_headers = array($columns, $hidden, $sortable);

		/** Process bulk action */
		$this->process_bulk_action();

		if ( isset( $_REQUEST['user_unblocked'] ) ) {
			?>
			<div class="notice notice-success is-dismissible">
				<p><?php printf( __( 'Subscriber Unblocked: %s', 'giveasap' ), sanitize_text_field( $_REQUEST['user_unblocked'] ) ); ?></p>
			</div>
			<?php
		}

		do_action( 'sg_subscriber_admin_list_before_items' );

		$per_page     = $this->get_items_per_page( 'sg_subscribers_per_page', 10 );
		$current_page = $this->get_pagenum();
		$total_items  = self::record_count();

		$this->set_pagination_args( [
			'total_items' => $total_items, //WE have to calculate the total number of items
			'per_page'    => $per_page //WE have to determine how many items to show on a page
		] );


		$this->items = self::get_entries( $per_page, $current_page );

	}

	public function process_bulk_action() {

		//Detect when a bulk action is being triggered...
		if ( 'delete' === $this->current_action() ) {

			// In our file that handles the request, verify the nonce.
			$nonce = esc_attr( $_REQUEST['delete_nonce'] );

			if ( ! wp_verify_nonce( $nonce, 'giveasap_delete_customer' ) ) {
				die( 'Go get a life script kiddies' );
			}
			else {
				self::delete_action( absint( $_GET['user'] ) );
			}

		}

		if ( 'activate' === $this->current_action() ) {
			giveasap_activate_user( absint( $_GET['user'] ) );
		}

		// If the delete bulk action is triggered
		if ( ( isset( $_POST['action'] ) && $_POST['action'] == 'bulk-delete' )
		     || ( isset( $_POST['action2'] ) && $_POST['action2'] == 'bulk-delete' )
		) {

			$delete_ids = esc_sql( $_POST['bulk-delete'] );

			// loop over the array of record IDs and delete them
			foreach ( $delete_ids as $id ) {
				self::delete_action( $id );

			}
		}
	}



	/**
	 * Extra controls to be displayed between bulk actions and pagination
	 *
	 * @since 2.10.0
	 *
	 * @param string $which
	 */
	protected function extra_tablenav( $which ) {
		if ( 'top' === $which ) {

		    $giveaway    = false;
		    $action_type = isset( $_REQUEST['action_type'] ) ? $_REQUEST['action_type'] : '';

		    if ( isset( $_REQUEST['giveaway'] ) ) {
		        $giveaway = sg_get_giveaway( $_REQUEST['giveaway'] );
            }

			?>
			<div class="alignleft actions">
                <select name="giveaway" placeholder="<?php echo esc_attr( 'Search for a giveaway', 'giveasap' ); ?>" class="sg-select2" style="width: 200px;">
                    <?php
                        if ( $giveaway ) {
                            ?>
                            <option value="<?php echo esc_attr( $giveaway->get_id() ); ?>"><?php echo wp_kses_post( $giveaway->get_post()->post_title )?></option>
                            <?php
                        }
                    ?>
                </select>
                <label for="sg_action_type">
                    <?php
                        esc_html_e( 'Action Type', 'giveasap' );
                    ?>
                    <select id="sg_action_type" name="action_type" style="width: 200px;float:none;">
                        <option value=""><?php esc_html_e( 'Show all', 'giveasap' ); ?></option>
					<?php
                    $actions = sg_get_registered_actions();
                    foreach ( $actions as $action_slug => $action_class ) {
                        if ( ! class_exists( $action_class ) ) {
                            continue;
                        }

                        $action_object = new $action_class();

	                    ?>
                        <option <?php selected( $action_type, $action_object->get_slug(), true ); ?> value="<?php echo esc_attr( $action_object->get_slug() ); ?>"><?php echo $action_object->get_title(); ?></option>
	                    <?php
                    }
					?>
                    </select>
                </label>
                <button class="button ga-filter-entries"><?php _e( 'Filter', 'giveasap' ); ?></button>

                <?php
                $subscriber_id  = isset( $_REQUEST['subscriber'] ) ? intval( $_REQUEST['subscriber'] ) : 0;
                $giveaway_id    = isset( $_REQUEST['giveaway'] ) ? absint( $_REQUEST['giveaway'] ) : 0;
                $action_type    = isset( $_REQUEST['action_type'] ) ? $_REQUEST['action_type'] : '';
                $export_payload = array(
                    'subscriber' => $subscriber_id,
                    'giveaway'   => $giveaway_id,
                    'action'     => $action_type
                );

                ?>

                <button type="submit" name="sg_export_entries" value="<?php echo esc_attr( wp_json_encode( $export_payload ) ); ?>" class="button button-secondary"><?php _e( 'Export Entries', 'giveasap' ); ?></button>
            </div>
			<?php
		}
	}

	/**
	 * Display the pagination.
	 *
	 * @since 3.1.0
	 *
	 * @param string $which
	 */
	protected function pagination( $which ) {
		if ( empty( $this->_pagination_args ) ) {
			return;
		}

		$total_items = $this->_pagination_args['total_items'];
		$total_pages = $this->_pagination_args['total_pages'];
		$infinite_scroll = false;
		if ( isset( $this->_pagination_args['infinite_scroll'] ) ) {
			$infinite_scroll = $this->_pagination_args['infinite_scroll'];
		}

		if ( 'top' === $which && $total_pages > 1 ) {
			$this->screen->render_screen_reader_content( 'heading_pagination' );
		}

		$output = '<span class="displaying-num">' . sprintf( _n( '%s item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . '</span>';

		$current = $this->get_pagenum();
		$removable_query_args = wp_removable_query_args();

		$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );

		$current_url = remove_query_arg( $removable_query_args, $current_url );
		$current_url = remove_query_arg( 'user_notified', $current_url );
		$current_url = remove_query_arg( 'user_blocked', $current_url );
		$current_url = remove_query_arg( 'user_unblocked', $current_url );
		$page_links  = array();

		if ( isset( $_REQUEST['giveaway'] ) ) {
		    $current_url = add_query_arg( 'giveaway', $_REQUEST['giveaway'], $current_url );
        }

		$total_pages_before = '<span class="paging-input">';
		$total_pages_after  = '</span></span>';

		$disable_first = $disable_last = $disable_prev = $disable_next = false;

		if ( $current == 1 ) {
			$disable_first = true;
			$disable_prev = true;
		}
		if ( $current == 2 ) {
			$disable_first = true;
		}
		if ( $current == $total_pages ) {
			$disable_last = true;
			$disable_next = true;
		}
		if ( $current == $total_pages - 1 ) {
			$disable_last = true;
		}

		if ( $disable_first ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&laquo;</span>';
		} else {
			$page_links[] = sprintf( "<a class='first-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
				esc_url( remove_query_arg( 'paged', $current_url ) ),
				__( 'First page' ),
				'&laquo;'
			);
		}

		if ( $disable_prev ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&lsaquo;</span>';
		} else {
			$page_links[] = sprintf( "<a class='prev-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
				esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ),
				__( 'Previous page' ),
				'&lsaquo;'
			);
		}

		if ( 'bottom' === $which ) {
			$html_current_page  = $current;
			$total_pages_before = '<span class="screen-reader-text">' . __( 'Current Page' ) . '</span><span id="table-paging" class="paging-input"><span class="tablenav-paging-text">';
		} else {
			$html_current_page = sprintf( "%s<input class='current-page' id='current-page-selector' type='text' name='paged' value='%s' size='%d' aria-describedby='table-paging' /><span class='tablenav-paging-text'>",
				'<label for="current-page-selector" class="screen-reader-text">' . __( 'Current Page' ) . '</label>',
				$current,
				strlen( $total_pages )
			);
		}
		$html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
		$page_links[] = $total_pages_before . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . $total_pages_after;

		if ( $disable_next ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&rsaquo;</span>';
		} else {
			$page_links[] = sprintf( "<a class='next-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
				esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ),
				__( 'Next page' ),
				'&rsaquo;'
			);
		}

		if ( $disable_last ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&raquo;</span>';
		} else {
			$page_links[] = sprintf( "<a class='last-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
				esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
				__( 'Last page' ),
				'&raquo;'
			);
		}

		$pagination_links_class = 'pagination-links';
		if ( ! empty( $infinite_scroll ) ) {
			$pagination_links_class .= ' hide-if-js';
		}
		$output .= "\n<span class='$pagination_links_class'>" . join( "\n", $page_links ) . '</span>';

		if ( $total_pages ) {
			$page_class = $total_pages < 2 ? ' one-page' : '';
		} else {
			$page_class = ' no-pages';
		}
		$this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";

		echo $this->_pagination;
	}
}