<?php
/**
 * Handles the attendee list shortcode functionality.
 *
 * @package rsvp-pro-plugin
 */

/**
 * Handles showing the attendee list on the front-end of a WordPress site.
 *
 * @param  int   $rsvp_id     The ID of the RSVP event we want to get the attendee list for.
 * @param  array $attributes The attributes for the shortcode.
 */
function rsvp_pro_attendeelist_frontend_handler( $rsvp_id, $attributes ) {
	global $wpdb;

	$wp_integration_enabled = ( 'Y' === rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_AUTO_LOGIN_ATTENDEE ) ) ? true : false;
	$show_profile           = ( 'Y' === rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_SHOW_PROFILE ) ) ? true : false;
	$has_sub_events         = false;
	$hide_rsvp_status       = ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_HIDE_STATUS ) === 'Y' ) ? true : false;
	if ( isset( $attributes['hide_status'] ) ) {
		$hide_rsvp_status = boolval( $attributes['hide_status'] );
	}
	$show_email = ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_SHOW_EMAIL ) === 'Y' ) ? true : false;
	if ( isset( $attributes['show_email'] ) ) {
		$tmp        = strtolower( $attributes['show_email'] );
		$show_email = ( ( 'true' === $tmp ) || ( 'y' === $tmp ) ) ? true : false;
	}
	$show_note = ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_SHOW_NOTE ) === 'Y' ) ? true : false;
	if ( isset( $attributes['show_note'] ) ) {
		$tmp       = strtolower( $attributes['show_note'] );
		$show_note = ( ( 'true' === $tmp ) || ( 'y' === $tmp ) ) ? true : false;
	}
	$show_associated = ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_SHOW_ASSOCIATED ) === 'Y' ) ? true : false;
	if ( isset( $attributes['show_associated'] ) ) {
		$tmp             = strtolower( $attributes['show_associated'] );
		$show_associated = ( ( 'true' === $tmp ) || ( 'y' === $tmp ) ) ? true : false;
	}
	$show_search = ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_SHOW_SEARCH ) === 'Y' ) ? true : false;
	if ( isset( $attributes['show_search'] ) ) {
		$tmp         = strtolower( $attributes['show_search'] );
		$show_search = ( ( 'true' === $tmp ) || ( 'y' === $tmp ) ) ? true : false;
	}
	$show_summary = ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_SHOW_SUMMARY ) === 'Y' ) ? true : false;
	if ( isset( $attributes['show_summary'] ) ) {
		$tmp          = strtolower( $attributes['show_summary'] );
		$show_summary = ( ( 'true' === $tmp ) || ( 'y' === $tmp ) ) ? true : false;
	}
	$allow_checkin = ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_ALLOW_CHECKIN ) === 'Y' ) ? true : false;
	if ( isset( $attributes['allow_checkin'] ) ) {
		$tmp           = strtolower( $attributes['allow_checkin'] );
		$allow_checkin = ( ( 'true' === $tmp ) || ( 'y' === $tmp ) ) ? true : false;
	}
	$change_status = ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_ALLOW_RSVP_CHANGE ) === 'Y' ) ? true : false;
	if ( isset( $attributes['allow_change_status'] ) ) {
		$tmp           = strtolower( $attributes['allow_change_status'] );
		$change_status = ( ( 'true' === $tmp ) || ( 'y' === $tmp ) ) ? true : false;
	}
	$custom_question_ids = rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_CUSTOM_QUESTIONS );
	if ( isset( $attributes['custom_questions'] ) ) {
		$custom_question_ids = explode( ',', $attributes['custom_questions'] );
	}
	$filters = rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_FILTER );
	if ( isset( $attributes['rsvp_statuses'] ) ) {
		$filters = explode( ',', $attributes['rsvp_statuses'] );
	}
	$sort_order = rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_SORT_ORDER );
	if ( isset( $attributes['sort_order'] ) ) {
		$sort_order = $attributes['sort_order'];
	}
	$show_qr_code = ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_SHOW_QR_PREFILL ) === 'Y' ) ? true : false;
	if ( isset( $attributes['show_qr_code'] ) ) {
		$tmp        = strtolower( $attributes['show_qr_code'] );
		$show_email = ( ( 'true' === $tmp ) || ( 'y' === $tmp ) ) ? true : false;
	}

	if ( isset( $_GET['sort'] ) && ! empty( $_GET['sort'] ) ) {
		$sort_order = $_GET['sort'];
	}

	$page_size     = 100;
	$tmp_page_size = rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_PAGE_SIZE );
	if ( ! empty( $tmp_page_size ) && is_numeric( $tmp_page_size ) && ( 0 < intval( $tmp_page_size ) ) ) {
		$page_size = intval( $tmp_page_size );
	} elseif( $tmp_page_size === 'all' ) {
		$page_size = 'all';
	}
	$event_url = rsvp_pro_get_event_permalink( $rsvp_id );

	$output           = "<div class=\"rsvp_pro_attendee_list_container\">\r\n";
	$subevent_count   = 0;
	$questions        = null;
	$q_ids            = array();
	$yes_text         = rsvp_pro_get_frontend_string( 'yes_text' );
	$no_text          = rsvp_pro_get_frontend_string( 'no_text' );
	$waitlist_text    = rsvp_pro_get_frontend_string( 'waitlist_text' );
	$waitlist_enabled = ( ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ENABLE_WAITLIST ) === 'Y' ) && rsvp_pro_frontend_max_limit_hit( $rsvp_id ) );

	$base_sql = 'SELECT COUNT(*) FROM ' . PRO_ATTENDEES_TABLE . ' a
    JOIN ' . PRO_EVENT_TABLE . ' e ON e.id = a.rsvpEventID
    WHERE ((IFNULL(e.event_access, \'' . RSVP_PRO_OPEN_EVENT_ACCESS . '\') != \'' . RSVP_PRO_PRIVATE_EVENT_ACCESS . '\') OR (a.id IN (SELECT rsvpAttendeeID FROM ' . PRO_EVENT_ATTENDEE_TABLE . ' WHERE rsvpEventID = e.id))) ';

	$yes_results        = $wpdb->get_var( $wpdb->prepare( $base_sql . " AND (rsvpStatus = 'Yes' or rsvpStatus = 'PlusOne') AND rsvpEventID = %d", $rsvp_id ) );
	$no_results         = $wpdb->get_var( $wpdb->prepare( $base_sql . " AND rsvpStatus = 'No' AND rsvpEventID = %d", $rsvp_id ) );
	$checked_in_results = $wpdb->get_var( $wpdb->prepare( $base_sql . " AND checked_in = 'Y' AND rsvpEventID = %d", $rsvp_id ) );

	if ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_PLUS_ONE_ENABLED ) === 'Y' ) {
		$yes_results        += $wpdb->get_var( $wpdb->prepare( $base_sql . " AND rsvpStatus = 'PlusOne' AND rsvpEventID = %d ", $rsvp_id ) );
		$checked_in_results += $wpdb->get_var( $wpdb->prepare( $base_sql . " AND checked_in = 'Y' AND rsvpEventID = %d AND rsvpStatus = 'PlusOne'", $rsvp_id ) );
	}

	if ( rsvp_pro_is_shared_attendee_list_enabled() ) {
		$base_sql = 'SELECT COUNT(*) FROM ' . PRO_ATTENDEES_TABLE . ' a 
			INNER JOIN ' . PRO_ATTENDEE_SUB_EVENTS_TABLE . ' se ON se.rsvpAttendeeID = a.id AND se.rsvpEventID = %d 
			LEFT JOIN ' . PRO_EVENT_TABLE . ' e ON e.id = se.rsvpEventID
			WHERE ((IFNULL(e.event_access, \'' . RSVP_PRO_OPEN_EVENT_ACCESS . '\') != \'' . RSVP_PRO_PRIVATE_EVENT_ACCESS . '\') OR (a.id IN (SELECT rsvpAttendeeID FROM ' . PRO_EVENT_ATTENDEE_TABLE . ' WHERE rsvpEventID = e.id))) AND ';

		$sql          = $base_sql . " (se.rsvpStatus = 'Yes' OR se.RsvpStatus = 'PlusOne') ";
		$yes_results += $wpdb->get_var( $wpdb->prepare( $sql, $rsvp_id ) );

		$sql         = $base_sql . " se.rsvpStatus = 'No'";
		$no_results += $wpdb->get_var( $wpdb->prepare( $sql, $rsvp_id ) );

		$sql                 = $base_sql . " se.checked_in = 'Y'";
		$checked_in_results += $wpdb->get_var( $wpdb->prepare( $sql, $rsvp_id ) );

		if ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_PLUS_ONE_ENABLED ) === 'Y' ) {
			$sql          = $base_sql . " se.rsvpStatus = 'PlusOne'";
			$yes_results += $wpdb->get_var( $wpdb->prepare( $sql, $rsvp_id ) );

			$sql                 = $base_sql . " se.checked_in = 'Y' AND se.rsvpStatus = 'PlusOne'";
			$checked_in_results += $wpdb->get_var( $wpdb->prepare( $sql, $rsvp_id ) );
		}
	}

	if ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_YES_TEXT ) != '' ) {
		$yes_text = rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_YES_TEXT );
	}

	if ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_NO_TEXT ) != '' ) {
		$no_text = rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_NO_TEXT );
	}

	if ( isset( $_POST['action'] ) && ( $_POST['action'] === 'check_in' ) ) {
		rsvp_pro_attendeelist_checkin_handler( $rsvp_id );
	}

	if ( isset( $_POST['alAction'] ) && ( $_POST['alAction'] == 'changeStatus' ) ) {
		rsvp_pro_attendeelist_change_status( $rsvp_id );
	}

	if ( is_array( $custom_question_ids ) &&
		( count( $custom_question_ids ) > 0 ) ) {

		// Get the valid question IDs.
		foreach ( $custom_question_ids as $id ) {
			if ( is_numeric( $id ) && ( $id > 0 ) ) {
				$q_ids[] = $id;
			}
		}

		if ( count( $q_ids ) > 0 ) {
			$sql       = 'SELECT id, question FROM ' . PRO_QUESTIONS_TABLE . '
    			WHERE rsvpEventID = %d AND id IN (' . implode( ',', $q_ids ) . ')
    			ORDER BY sortOrder, id';
			$questions = $wpdb->get_results( $wpdb->prepare( $sql, $rsvp_id ) );
		}
	}

	// Check to see if it has subevents and if so handle the query slightly differently.
	$sql       = 'SELECT eventName, id FROM ' . PRO_EVENT_TABLE . ' WHERE parentEventID = %d ORDER BY id';
	$subevents = $wpdb->get_results( $wpdb->prepare( $sql, $rsvp_id ) );
	if ( count( $subevents ) > 0 ) {
		$has_sub_events = true;
	}
	$field_list = 'SELECT a.id, firstName, lastName, IFNULL(se.checked_in, a.checked_in) as checked_in, 
        IFNULL(se.rsvpStatus, a.rsvpStatus) as rsvpStatus, 
        IFNULL(ese.eventName, e.eventName) AS eventName, IFNULL(ese.id, e.id) AS eventId, a.email, a.note, a.token ';
	$sql        = ' FROM ' . PRO_ATTENDEES_TABLE . ' a
    	LEFT JOIN ' . PRO_EVENT_TABLE . ' e ON e.id = a.rsvpEventId 
        LEFT JOIN ' . PRO_ATTENDEE_SUB_EVENTS_TABLE . ' se ON se.rsvpAttendeeID = a.id AND se.rsvpEventID = %d 
        LEFT JOIN ' . PRO_EVENT_TABLE . ' ese ON ese.id = se.rsvpEventID ';

	foreach ( $subevents as $se ) {
		$field_list .= ', se' . $subevent_count . '.eventName AS se' . $subevent_count . 'EventName,
			sea' . $subevent_count . '.rsvpStatus AS sea' . $subevent_count . 'RsvpStatus,
			se' . $subevent_count . '.id AS se' . $subevent_count . 'EventId,
			sea' . $subevent_count . '.checked_in AS sea' . $subevent_count . 'Checked_In ';

		$sql .= ' LEFT JOIN ' . PRO_EVENT_TABLE . " se$subevent_count ON se" . $subevent_count . '.id = ' . $se->id .
			' LEFT JOIN ' . PRO_ATTENDEE_SUB_EVENTS_TABLE . ' sea' . $subevent_count . ' ON sea' . $subevent_count . '.rsvpEventId = ' . $se->id . ' AND sea' . $subevent_count . '.rsvpAttendeeID = a.id ';

		$subevent_count++;
	}

	$sql_where = ' WHERE ( (a.rsvpEventId = %d) ';

	if ( rsvp_pro_is_shared_attendee_list_enabled() ) {
		$sql_where .= ' OR (a.rsvpEventId = ' . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . ')';
	}

	$sql_where .= ' )';

	if ( is_array( $filters ) && ( count( $filters ) > 0 ) ) {
		$statuses = '';
		foreach ( $filters as $filter ) {
			if ( rsvp_pro_is_allowed_status( $filter ) ) {
				if ( ! empty( $statuses ) ) {
					$statuses .= ',';
				}
				$statuses .= "'" . $filter . "'";
			}
		}

		if ( strlen( $statuses ) > 0 ) {
			$sql_where .= " AND ( a.rsvpStatus IN ($statuses) OR ( a.rsvpEventID = " . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . " AND se.rsvpStatus IN ($statuses ) AND (se.rsvpEventID = $rsvp_id ) ) ) ";
		}
	} elseif ( ! empty( $filters ) ) {
		$sql_where .= " AND ( a.rsvpStatus = '" . esc_sql( $filters ) . "' OR (a.rsvpEventID = " . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . " AND a.rsvpStatus = '" . esc_sql( $filters ) . "' AND (se.rsvpEventID = $rsvp_id ) )) ";
	}

	if ( isset( $_GET['search'] ) && ! empty( $_GET['search'] ) ) {
		$search_val = esc_sql( $_GET['search'] );
		$sql_where .= " AND ( (CONCAT_WS(' ', a.firstName, a.lastName) LIKE '%%$search_val%%') ";

		if ( ( null !== $questions ) && ( count( $questions ) > 0 ) ) {
			$sql_where .= 'OR ( a.id IN (SELECT attendeeID FROM ' . PRO_QUESTIONS_TABLE . ' q
				INNER JOIN ' . PRO_ATTENDEE_ANSWERS . ' aa ON aa.questionID = q.id
				WHERE q.id IN(' . implode( ',', $q_ids ) . ") AND aa.answer LIKE '%%$search_val%%') ) ";
		}

		$sql_where .= ' ) ';
	}

	$sort_by = 'a.lastName, a.firstName';

	if ( '' !== $sort_order ) {
		if ( stripos( $sort_order, 'cq_' ) !== false ) {
			$cq_id = str_replace( 'cq_', '', $sort_order );
			if ( is_numeric( $cq_id ) && ( $cq_id > 0 ) ) {
				$sql    .= ' LEFT JOIN ' . PRO_ATTENDEE_ANSWERS . ' aa  ON aa.attendeeID = a.id AND aa.questionID = ' . $cq_id;
				$sort_by = 'aa.answer';
			}
		} elseif ( 'rsvpDate' == $sort_order ) {
			$sort_by = 'a.rsvpDate DESC';
		} else {
			$sort_by = 'a.' . esc_sql( $sort_order );
		}
	}

	$sql .= $sql_where;
	$sql .= " ORDER BY $sort_by ";

	$attendee_count = $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) ' . $sql, $rsvp_id, $rsvp_id ) );
	$paged          = isset( $_GET['attendees_page'] ) ? absint( $_GET['attendees_page'] ) : 0;

	if ( ! is_numeric( $paged ) || ( $paged < 1 ) || ( ( ( $paged - 1 ) * $page_size ) > $attendee_count ) ) {
		$paged = 0;
	} else {
		$paged--;
	}

	if ( $page_size !== 'all' ) {
		$sql      .= ' LIMIT ' . ( $paged * $page_size ) . ", $page_size ";
	}
	$attendees = $wpdb->get_results( $wpdb->prepare( $field_list . $sql, $rsvp_id, $rsvp_id ) );

	if ( $show_search ) {
		$search_text = rsvp_pro_get_frontend_string( 'search_attendee_list_text' );

		if ( '' != rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_FILTER_TEXT ) ) {
			$search_text = rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_FILTER_TEXT );
		}

		$output .= '<div id="rsvp_attendeelist_search_container">';
		$output .= '<form name="attendee_list_search" method="get">';
		$output .= '<label>
			<input type="text" name="search" />
			<input type="submit" value="' . $search_text . '" />
		</label>';
		$output .= '</form>
			</div>';
	}

	if ( count( $attendees ) > 0 ) {
		$check_in_text   = rsvp_pro_get_frontend_string( 'check_in_label' );
		$checked_in_text = rsvp_pro_get_frontend_string( 'already_checked_in_label' );

		if ( '' != rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_CHECKIN_TEXT ) ) {
			$check_in_text = rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_CHECKIN_TEXT );
		}

		if ( '' != rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_CHECKED_IN_TEXT ) ) {
			$checked_in_text = rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_CHECKED_IN_TEXT );
		}

		if ( 'Y' === rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_ATTENDEE_LIST_EXPORT_BUTTON ) ) {
			$output .= '<div id="rsvp_pro_attendee_list_export_button_container">';
			$output .= '<form method="get">';
			$output .= '<input type="hidden" name="attendee_list_action" value="export" />';
			$output .= '<input type="hidden" name="eventID" value="' . $rsvp_id . '" />';
			$output .= '<input type="submit" value="' . rsvp_pro_get_frontend_string( 'export_attendee_list_button_text' ) . '" />';
			$output .= '</form>';
			$output .= '</div>';
		}

		if ( $show_summary ) {
			$output .= '<div class="rsvp_pro_attendee_list_summary" id="rsvp_pro_attendee_list_summary_header">';
			$output .= '<p class="rsvpParagraph">' . rsvp_pro_humanize_rsvp_status( 'Yes' ) . ': ' . $yes_results . '</p>';
			$output .= '<p class="rsvpParagraph">' . rsvp_pro_humanize_rsvp_status( 'No' ) . ': ' . $no_results . '</p>';

			if ( $allow_checkin ) {
				$output .= '<p class="rsvpParagraph">' . $check_in_text . ': ' . $checked_in_results . '</p>';
			}

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

		if ( ( $page_size !== 'all' ) && ( $attendee_count > $page_size ) ) {
			$output .= '<div class="rsvp_pro_attendee_list_pagination">';
			for ( $i = 0; $i < ( ceil( $attendee_count / $page_size ) ); $i++ ) {
				$output .= '<a href="' . add_query_arg( 'attendees_page', ( $i + 1 ) ) . '" class="rsvp-pro-attendee-list-page-numbers">' . ( $i + 1 ) . '</a>';
			}
			$output .= '</div>';
		}

		$titles = array(
			'check_in'             => $check_in_text,
			'name'                 => rsvp_pro_get_frontend_string( 'name_label' ),
			'email'                => rsvp_pro_get_frontend_string( 'email_label' ),
			'note'                 => rsvp_pro_get_frontend_string( 'note_label' ),
			'rsvp_status'          => rsvp_pro_get_frontend_string( 'rsvp_status_label' ),
			'change_status'        => rsvp_pro_get_frontend_string( 'change_rsvp_status_label' ),
			'associated_attendees' => rsvp_pro_get_frontend_string( 'associated_attendees_label' ),
			'qr_code'              => rsvp_pro_get_frontend_string( 'qr_prefill_label' ),
		);

		if ( ( null != $questions ) && ( count( $questions ) > 0 ) ) {
			foreach ( $questions as $q ) {
				$question_text            = stripslashes( $q->question );
				$key_name                 = stripslashes( rsvp_pro_get_event_name( $rsvp_id ) . ' - ' . $question_text );
				$question_text            = rsvp_pro_get_dynamic_translated_string( $key_name, $question_text, $rsvp_id );
				$titles[ 'cq_' . $q->id ] = $question_text;
			}
		}

		$output .= '<a name="rsvpAttendees"></a>';
		$output .= '<div id="rsvp_pro_attendee_list_table_container">';
		$output .= '<table class="rsvp_pro_attendee_list_table">
			<thead>
				<tr>';

		if ( $allow_checkin ) {
			$output .= '<th class="rsvp_pro_attendee_list_checkin">' . $titles['check_in'] . '</th>';
		}
		$output .= '<th class="rsvp_pro_attendee_list_name"><a href="' . add_query_arg( 'sort', 'lastName' ) . '">' . $titles['name'] . '</a></th>';

		if ( $show_email ) {
			$output .= '<th class="rsvp_pro_attendee_list_email"><a href="' . add_query_arg( 'sort', 'email' ) . '">' . $titles['email'] . '</a></th>';
		}

		if ( ! $hide_rsvp_status ) {
			$output .= '<th class="rsvp_pro_attendee_list_rsvp_status"><a href="' . add_query_arg( 'sort', 'rsvpStatus' ) . '">' . $titles['rsvp_status'] . '</a></th>';
		}

		if ( $change_status ) {
			$output .= '<th class="rsvp_pro_attendee_list_change_rsvp_status">' . $titles['change_status'] . '</th>';
		}

		if ( $show_associated ) {
			$output .= '<th class="rsvp_pro_attendee_list_associated">' . $titles['associated_attendees'] . '</th>';
		}

		if ( $show_note ) {
			$output .= '<th class="rsvp_pro_attendee_list_note"><a href="' . add_query_arg( 'sort', 'note' ) . '">' . $titles['note'] . '</a></th>';
		}

		if ( $show_qr_code ) {
			$output .= '<th class="rsvp_pro_attendee_list_qr_prefill">' . $titles['qr_code'] . '</th>';
		}

		if ( ( null != $questions ) && ( count( $questions ) > 0 ) ) {
			foreach ( $questions as $q ) {
				$output .= '<th class="rsvp_pro_attendee_list_cq' . $q->id . '"><a href="' . add_query_arg( 'sort', 'cq_' . $q->id ) . '">' . esc_html( $titles[ 'cq_' . $q->id ] ) . "</a></th>\r\n";
			}
		}

		$output .= '</tr>
			</thead>
		<tbody>';
		foreach ( $attendees as $a ) {
			$output .= "<tr>\r\n";

			if ( $allow_checkin ) {
				$output .= '<td class="rsvp_pro_attendee_list_checkin" data-title="' . esc_html( $titles['check_in'] ) . '">';

				if ( $has_sub_events && ( $a->eventId != RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID ) ) {
					$output .= esc_html( $a->eventName ) . '<br />';
				}

				$output .= '<form method="post">
					<input type="hidden" name="action" value="check_in" />
					<input type="hidden" name="rsvp_id" value="' . $rsvp_id . '" />
					<input type="hidden" name="attendee_id" value="' . $a->id . '" />
					<input type="hidden" name="check_in_value" value="' . ( ( 'Y' == $a->checked_in ) ? 'N' : 'Y' ) . '" />
					<input type="submit" value="' . ( ( 'Y' == $a->checked_in ) ? $checked_in_text : $check_in_text ) . '" />
				</form>';

				if ( $has_sub_events ) {
					for ( $i = 0; $i < $subevent_count; $i++ ) {
						if ( $a->{'se' . $i . 'EventId'} != RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID ) {
							$check_in_status = $a->{'sea' . $i . 'Checked_In'};

							$output .= esc_html( $a->{'se' . $i . 'EventName'} ) . '<br />';
							$output .= '<form method="post">
							<input type="hidden" name="action" value="check_in" />
							<input type="hidden" name="rsvp_id" value="' . $a->{'se' . $i . 'EventId'} . '" />
							<input type="hidden" name="attendee_id" value="' . $a->id . '" />
							<input type="hidden" name="check_in_value" value="' . ( ( 'Y' == $check_in_status ) ? 'N' : 'Y' ) . '" />
							<input type="submit" value="' . ( ( 'Y' == $check_in_status ) ? $checked_in_text : $check_in_text ) .
							'" />
							</form>';
						}
					}
				}

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

			$output .= '<td class="rsvp_pro_attendee_list_name" data-title="' . esc_html( $titles['name'] ) . '">';

			if ( $show_profile ) {
				$user = get_user_by( 'email', $a->email );
				if ( false !== $user ) {
					$output .= get_avatar( $user->ID );
				}
			}

			$output .= esc_html( stripslashes( $a->firstName . ' ' . $a->lastName ) ) . "</td>\r\n";

			if ( $show_email ) {
				$output .= '<td class="rsvp_pro_attendee_list_email" data-title="' . esc_html( $titles['email'] ) . '">' . esc_html( stripslashes( $a->email ) ) . "</td>\r\n";
			}

			if ( ! $hide_rsvp_status ) {
				$output .= '<td class="rsvp_pro_attendee_list_rsvp_status" data-title="' . esc_html( $titles['rsvp_status'] ) . '">';
				if ( $has_sub_events ) {
					if ( $a->eventId != RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID ) {
						$output .= esc_html( stripslashes( $a->eventName ) ) . ' - ' .
							rsvp_pro_humanize_rsvp_status( $a->rsvpStatus, $a->eventId );
					}

					for ( $i = 0; $i < $subevent_count; $i++ ) {
						if ( $a->{'se' . $i . 'EventId'} != RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID ) {
							$status = $a->{'sea' . $i . 'RsvpStatus'};
							if ( empty( $status ) ) {
								$status = 'NoResponse';
							}
							$output .= "<br />\r\n &nbsp; " .
								esc_html( stripslashes( $a->{'se' . $i . 'EventName'} ) ) . ' - ' .
								rsvp_pro_humanize_rsvp_status( $status, $a->eventId );
						}
					}
				} else {
					$output .= rsvp_pro_humanize_rsvp_status( $a->rsvpStatus, $a->eventId );
				}
				$output .= "</td>\r\n";
			}

			if ( $change_status ) {
				$output .= '<td class="rsvp_pro_attendee_list_change_rsvp_status" data-title="' . $titles['change_status'] . '">';
				$output .= '<form name="attendeeListRsvpStatus" method="post">';
				$output .= '<input type="hidden" name="alAction" value="changeStatus" />';
				$output .= '<input type="hidden" name="attendeeID" value="' . $a->id . '" />';
				$output .= rsvp_pro_get_frontend_string( 'change_status_to_label' );

				$lowered_rsvp_status = strtolower( $a->rsvpStatus );
				if ( ( 'yes' == $lowered_rsvp_status ) || ( 'waitlist' == $lowered_rsvp_status ) ) {
					$output .= '<input type="hidden" name="rsvpStatus" value="N" />';
					$output .= esc_html( $no_text );
				} elseif ( ( 'no' == $lowered_rsvp_status ) && ! $waitlist_enabled ) {
					$output .= '<input type="hidden" name="rsvpStatus" value="Y" />';
					$output .= esc_html( $yes_text );
				} elseif ( ( 'no' == $lowered_rsvp_status ) && $waitlist_enabled ) {
					$output .= '<input type="hidden" name="rsvpStatus" value="W" />';
					$output .= $waitlist_text;
				} elseif ( 'noresponse' == $lowered_rsvp_status ) {
					$output .= '<select name="rsvpStatus" size="1">';
					if ( $waitlist_enabled ) {
						$output .= '<option value="W">' . esc_html( $waitlist_text ) . '</option>';
					} else {
						$output .= '<option value="Y">' . esc_html( $yes_text ) . '</option>';
					}

					$output .= '<option value="N">' . esc_html( $no_text ) . '</option>';
					$output .= "</select>\r\n";
				}

				$output .= '<p class="rsvpAttendeeSubmitButton submit_button">';
				$output .= '<input type="submit" value="' . rsvp_pro_get_frontend_string( 'submit_label' ) . '" />';
				$output .= '</p>';
				$output .= '</form>';
				$output .= '</td>';
			}

			if ( $show_associated ) {
				$output      .= '<td class="rsvp_pro_attendee_list_associated" data-title="' . $titles['associated_attendees'] . '">';
				$sql          = 'SELECT firstName, lastName FROM ' . PRO_ATTENDEES_TABLE . ' a
					JOIN ' . PRO_EVENT_TABLE . ' e ON e.id = a.rsvpEventID
					WHERE (a.id IN (SELECT attendeeID FROM ' . PRO_ASSOCIATED_ATTENDEES_TABLE . ' WHERE associatedAttendeeID = %d)
                        OR a.id in (SELECT associatedAttendeeID FROM ' . PRO_ASSOCIATED_ATTENDEES_TABLE . ' WHERE attendeeID = %d)) ';
				$associations = $wpdb->get_results( $wpdb->prepare( $sql, $a->id, $a->id ) );
				foreach ( $associations as $assoc ) {
					$output .= esc_html( stripslashes( $assoc->firstName . ' ' . $assoc->lastName ) ) . '<br />';
				}
				$output .= "</td>\r\n";
			}

			if ( $show_note ) {
				$output .= '<td class="rsvp_pro_attendee_list_note" data-title="' . esc_html( $titles['note'] ) . '">' . esc_html( stripslashes_deep( $a->note ) ) . "</td>\r\n";
			}

			if ( $show_qr_code ) {
				$prefill_url_token = add_query_arg( 
					array(
						'token' => urlencode( $a->token ),
					),
					$event_url
				);
				$file_path   = rsvp_pro_generate_prefill_qr( $prefill_url_token, $a->token );
				$qr_url_path = str_replace( WP_CONTENT_DIR, '/wp-content', $file_path );
				$output     .= '<td class="rsvp_pro_attendee_list_qr_prefill"><img src="' . $qr_url_path . '" /></td>';
			}

			if ( ( null != $questions ) && ( count( $questions ) > 0 ) ) {
				$sql     = 'SELECT q.id, GROUP_CONCAT(aa.answer SEPARATOR \' \') AS answer, q.question FROM ' . PRO_QUESTIONS_TABLE . ' q
    				LEFT JOIN ' . PRO_ATTENDEE_ANSWERS . ' aa ON aa.questionID = q.id AND attendeeID = %d
    				WHERE q.id IN( ' . implode( ',', $q_ids ) . ')
                    GROUP BY q.id 
					ORDER BY sortOrder, q.id ';
				$answers = $wpdb->get_results( $wpdb->prepare( $sql, $a->id ) );
				foreach ( $answers as $ans ) {
					$answer_text = stripslashes( $ans->answer );
					$key_name    = stripslashes( $ans->question . ' - ' . $ans->answer );
					$answer_text = rsvp_pro_get_dynamic_translated_string( $key_name, $answer_text, $rsvp_id );

					$output .= '<td class="rsvp_pro_attendee_list_cq' . $ans->id . '" data-title="' . $titles[ 'cq_' . $ans->id ] . '">' . ( ( '' != $ans->answer ) ? esc_html( stripslashes( $answer_text ) ) : '&nbsp;' ) . "</td>\r\n";
				}
			}

			$output .= "</tr>\r\n";
		}
		$output .= '</tbody>
    		</table>
    	</div>';

		if ( ( $page_size !== 'all' ) && ( $attendee_count > $page_size ) ) {
			$output .= '<div class="rsvp_pro_attendee_list_pagination">';
			for ( $i = 0; $i < ( ceil( $attendee_count / $page_size ) ); $i++ ) {
				$output .= '<a href="?attendees_page=' . ( $i + 1 ) . '" class="rsvp-pro-attendee-list-page-numbers">' . ( $i + 1 ) . '</a>';
			}
			$output .= '</div>';
		}

		if ( $show_summary ) {
			$output .= '<div class="rsvp_pro_attendee_list_summary" id="rsvp_pro_attendee_list_summary_footer">';
			$output .= '<p class="rsvpParagraph">' . rsvp_pro_humanize_rsvp_status( 'Yes' ) . ': ' . $yes_results . '</p>';
			$output .= '<p class="rsvpParagraph">' . rsvp_pro_humanize_rsvp_status( 'No' ) . ': ' . $no_results . '</p>';

			if ( $allow_checkin ) {
				$output .= '<p class="rsvpParagraph">' . $check_in_text . ': ' . $checked_in_results . '</p>';
			}

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

	$output .= "</div>\r\n";

	return $output;
}

/**
 * Changes the attendee list RSVP status.
 *
 * @param  int $rsvp_id The event ID we want to change the RSVP status for.
 */
function rsvp_pro_attendeelist_change_status( $rsvp_id ) {
	global $wpdb;

	if ( isset( $_POST['attendeeID'] ) && ( intval( $_POST['attendeeID'] ) > 0 ) ) {
		if ( 'Y' == strToUpper( $_POST['rsvpStatus'] ) ) {
			$new_status = 'Yes';
		} elseif ( 'W' == strToUpper( $_POST['rsvpStatus'] ) ) {
			$new_status = 'Waitlist';
		} else {
			$new_status = 'No';
		}

		$wpdb->update(
			PRO_ATTENDEES_TABLE,
			array( 'rsvpStatus' => $new_status ),
			array(
				'id'          => $_POST['attendeeID'],
				'rsvpEventID' => $rsvp_id,
			),
			array( '%s' ),
			array( '%d', '%d' )
		);
	}
}

/**
 * Handles the checking in of an attendee for an event.
 *
 * @param  int $rsvp_id The event ID we want to handle the check-in for.
 */
function rsvp_pro_attendeelist_checkin_handler( $rsvp_id ) {
	global $wpdb;

	if ( isset( $_POST['attendee_id'] ) && is_numeric( $_POST['attendee_id'] ) &&
		( $_POST['attendee_id'] > 0 ) ) {
		$rsvp_to_handle = $rsvp_id;

		if ( isset( $_POST['rsvp_id'] ) && is_numeric( $_POST['rsvp_id'] ) &&
			( $_POST['rsvp_id'] > 0 ) ) {
			$rsvp_to_handle = $_POST['rsvp_id'];
		}

		$check_in = 'Y';

		if ( isset( $_POST['check_in_value'] ) &&
			( 'N' === $_POST['check_in_value'] ) ) {
			$check_in = 'N';
		}

		rsvp_pro_handle_attendee_check_in( $rsvp_to_handle, $_POST['attendee_id'], $check_in );
	}
}
