<?php
/*
 Note: I don't really like to have a utils file but this is a first
 step to refactoring the many different functions that are being
 used in this plugin.
*/

/**
 * Description: Database setup for the rsvp plug-in.
 */
function rsvp_pro_database_setup() {
	global $wpdb;
	rsvp_pro_update_database( $wpdb );
}

/**
 * Gets option information for a given event. It can handle multiple events.
 *
 * @param  int    $event_id The event we are trying to get the information for.
 * @param  string $option_name The option name we want the information for.
 *
 * @return mixed               The value from the option we are looking for.
 */
function rsvp_pro_get_event_option( $event_id, $option_name ) {
	global $wpdb;
	global $rsvp_options;

	$value   = '';
	$options = null;

	if ( isset( $rsvp_options[ $event_id ] ) && is_array( $rsvp_options[ $event_id ] ) ) {
		$options = $rsvp_options[ $event_id ];
	} elseif ( strcasecmp( $wpdb->get_var( 'SHOW TABLES LIKE \'' . PRO_EVENT_TABLE . '\'' ), PRO_EVENT_TABLE ) === 0 ) {
		$options = $wpdb->get_var( $wpdb->prepare( 'SELECT options FROM ' . PRO_EVENT_TABLE . ' WHERE id = %d', $event_id ) );
		if ( ! empty( $options ) ) {
			$options = json_decode( $options, true );
		}
		$rsvp_options[ $event_id ] = $options;
	}

	if ( is_array( $options ) && isset( $options[ $option_name ] ) ) {
		if ( is_array( $options[ $option_name ] ) ) {
			$value = $options[ $option_name ];
		} else {
			$value = stripslashes( $options[ $option_name ] );
			$key   = rsvp_pro_get_event_name( $event_id ) . ' - ' . $option_name;
			$value = rsvp_pro_get_dynamic_translated_string( $key, $value, $event_id );
		}
	}

	return $value;
}

function rsvp_pro_get_sub_event_option( $subEventId, $option_name ) {
	global $wpdb;
	global $rsvp_sub_options;
	$value = '';

	if ( isset( $rsvp_sub_options[ $subEventId ] ) && is_array( $rsvp_sub_options[ $subEventId ] ) ) {
		$options = $rsvp_sub_options[ $subEventId ];
	} else {
		$options = $wpdb->get_var( $wpdb->prepare( 'SELECT options FROM ' . PRO_EVENT_TABLE . ' WHERE id = %d', $subEventId ) );
		if ( ! empty( $options ) ) {
			$options = json_decode( $options, true );
		}
		$rsvp_sub_options[ $subEventId ] = $options;
	}
	if ( is_array( $options ) && isset( $options[ $option_name ] ) ) {
		if ( is_array( $options[ $option_name ] ) ) {
			$value = $options[ $option_name ];
		} else {
			$value = stripslashes( $options[ $option_name ] );
			$key   = rsvp_pro_get_event_name( $subEventId ) . ' - ' . $option_name;
			$value = rsvp_pro_get_dynamic_translated_string( $key, $value, $subEventId );
		}
	}

	return $value;
}

function rsvp_pro_get_event_information( $eventId, $informationKey ) {
	global $wpdb;
	global $event_information;

	if ( $event_information === null ) {
		$event_information = array();
	}

	if ( ( count( $event_information ) <= 0 ) || ( $event_information[ RSVP_PRO_INFO_EVENT_ID ] != $eventId ) ) {
		$info = $wpdb->get_row(
			$wpdb->prepare(
				'SELECT id, eventName, open_date, close_date, event_access,
					eventStartDate, eventEndDate, eventLocation, eventDescription, 
					open_date_time, open_date_timezone, close_date_time, close_date_timezone, 
					attendee_list_sent_on, attendee_columns, eventStartDateTimezone, eventEndDateTimezone
					FROM ' . PRO_EVENT_TABLE . ' WHERE id = %d',
				$eventId
			)
		);
		if ( $info ) {
			$event_information[ RSVP_PRO_INFO_EVENT_NAME ]   = stripslashes( $info->eventName );
			$event_information[ RSVP_PRO_INFO_OPEN_DATE ]    = date( 'm/d/Y', strtotime( $info->open_date ) );
			$event_information[ RSVP_PRO_INFO_CLOSE_DATE ]   = date( 'm/d/Y', strtotime( $info->close_date ) );
			$event_information[ RSVP_PRO_INFO_EVENT_ID ]     = $info->id;
			$event_information[ RSVP_PRO_INFO_EVENT_ACCESS ] = $info->event_access;

			if ( strtotime( $info->eventStartDate ) && ( $info->eventStartDate != '0000-00-00 00:00:00' ) ) {
				$time_zone = new DateTimeZone( rsvp_pro_wp_get_timezone_string() );
				$tmp_date  = new DateTime( $info->eventStartDate, new DateTimeZone( 'UTC' ) );

				$tmp_date->setTimeZone( $time_zone );

				if ( ! empty( $info->eventStartDateTimezone ) ) {

					if ( preg_match( '/^UTC[+-]/', $info->eventStartDateTimezone ) ) {
						$event_timezone = preg_replace( '/UTC?/', '', $info->eventStartDateTimezone );
					} else {
						$event_timezone = $info->eventStartDateTimezone;
					}
					$tmp_time_zone = new DateTimeZone( $event_timezone );
					$tmp_date->setTimeZone( $tmp_time_zone );
				}

				$event_information[ RSVP_PRO_INFO_EVENT_START_DATE ] = $tmp_date->format( 'Y-m-d H:i:s' );
			}

			if ( strtotime( $info->eventEndDate ) && ( $info->eventEndDate != '0000-00-00 00:00:00' ) ) {
				$time_zone = new DateTimeZone( rsvp_pro_wp_get_timezone_string() );
				$tmp_date  = new DateTime( $info->eventEndDate, new DateTimeZone( 'UTC' ) );
				$tmp_date->setTimeZone( $time_zone );

				if ( ! empty( $info->eventEndDateTimezone ) ) {

					if ( preg_match( '/^UTC[+-]/', $info->eventEndDateTimezone ) ) {
						$event_timezone_end = preg_replace( '/UTC?/', '', $info->eventEndDateTimezone );
					} else {
						$event_timezone_end = $info->eventEndDateTimezone;
					}

					$tmp_time_zone = new DateTimeZone($event_timezone_end );
					$tmp_date->setTimeZone( $tmp_time_zone );
				}

				$event_information[ RSVP_PRO_INFO_EVENT_END_DATE ] = $tmp_date->format( 'Y-m-d H:i:s' );
			}
			$event_information[ RSVP_PRO_INFO_LOCATION ]              = rsvp_pro_get_dynamic_translated_string( rsvp_pro_get_event_name( $eventId ) . ' - ' . rsvp_pro_get_frontend_string( 'event_location_label' ), stripslashes( $info->eventLocation ), $eventId );
			$event_information[ RSVP_PRO_INFO_DESCRIPTION ]           = rsvp_pro_get_dynamic_translated_string( rsvp_pro_get_event_name( $eventId ) . ' - ' . rsvp_pro_get_admin_string( 'settings_event_description_label' ), stripslashes( $info->eventDescription ), $eventId );
			$event_information[ RSVP_PRO_INFO_OPEN_DATE_TIME ]        = stripslashes( $info->open_date_time );
			$event_information[ RSVP_PRO_INFO_OPEN_DATE_TIMEZONE ]    = stripslashes( $info->open_date_timezone );
			$event_information[ RSVP_PRO_INFO_CLOSE_DATE_TIME ]       = stripslashes( $info->close_date_time );
			$event_information[ RSVP_PRO_INFO_CLOSE_DATE_TIMEZONE ]   = stripslashes( $info->close_date_timezone );
			$event_information[ RSVP_PRO_INFO_ATTENDEE_LIST_COLUMNS ] = array_filter( explode( ',', stripslashes( $info->attendee_columns ) ) );
		}
	}

	return isset( $event_information[ $informationKey ] ) ? $event_information[ $informationKey ] : false;
}

function rsvp_pro_require_passcode( $rsvpId ) {
	if ( ( rsvp_pro_get_event_option( $rsvpId, RSVP_PRO_OPTION_OPEN_REGISTRATION ) == 'Y' ) && ( rsvp_pro_get_event_option( $rsvpId, RSVP_PRO_OPTION_RSVP_OPEN_NO_PASSCODE ) == 'Y' ) ) {
		return false;
	}

	if ( rsvp_pro_get_event_option( $rsvpId, RSVP_PRO_OPTION_PASSCODE ) == 'Y' ) {
		return true;
	}

	if ( rsvp_pro_get_event_option( $rsvpId, RSVP_PRO_OPTION_OPEN_REGISTRATION ) == 'Y' ) {
		return true;
	}

	if ( rsvp_pro_get_event_option( $rsvpId, RSVP_PRO_ONLY_PASSCODE ) == 'Y' ) {
		return true;
	}

	return false;
}

function rsvp_pro_require_only_passcode_to_register( $rsvpId ) {
	return ( rsvp_pro_get_event_option( $rsvpId, RSVP_PRO_ONLY_PASSCODE ) == 'Y' );
}

function rsvp_pro_require_unique_passcode( $rsvpId ) {
	return rsvp_pro_require_only_passcode_to_register( $rsvpId );
}

function rsvp_pro_waitlist_enabled( $rsvpId ) {
	if ( rsvp_pro_get_event_option( $rsvpId, RSVP_PRO_OPTION_ENABLE_WAITLIST ) == 'Y' ) {
		return true;
	}

	return false;
}

/**
 * This generates a random 6 character passcode to be used for guests when the option is enabled.
 */
function rsvp_pro_generate_passcode( $length = 6 ) {
	$characters = '0123456789abcdefghijklmnopqrstuvwxyz';
	$passcode   = '';

	for ( $p = 0; $p < $length; $p ++ ) {
		$passcode .= $characters[ mt_rand( 0, ( strlen( $characters ) - 1 ) ) ];
	}

	return $passcode;
}

function rsvp_pro_is_free_rsvp_installed() {
	global $wpdb;

	$table = $wpdb->prefix . 'attendees';

	return ( $wpdb->get_var( "SHOW TABLES LIKE '$table'" ) == $table );
}

function rsvp_pro_update_db_check() {
	global $wpdb;
	if ( get_option( 'rsvp_pro_db_version' ) != RSVP_PRO_DB_VERSION ) {
		require_once 'rsvp-db-setup.inc.php';
		rsvp_pro_update_database( $wpdb );
	}
}

function rsvp_pro_getCurrentPageURL() {
	global $rsvp_id;
	global $wp;
	global $wp_rewrite;

	if ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_FORM_URL ) !== '' ) {
		return rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_FORM_URL );
	}

	$page_url = home_url( $wp->request );

	if ( $wp_rewrite->using_index_permalinks() && ( strpos( $page_url, 'index.php' ) === false ) ) {
		$parts = parse_url( $page_url );

		$page_url = $parts['scheme'] . '://' . $parts['host'];

		if ( isset( $parts['port'] ) ) {
			$page_url .= ':' . $parts['port'];
		}

		$page_url .= '/index.php' . $parts['path'];

		if ( isset( $parts['query'] ) && ( $parts['query'] != '' ) ) {
			$page_url .= '?' . $parts['query'];
		}
	} elseif ( empty( $wp_rewrite->permalink_structure ) ) {
		$page_url = get_permalink();
	}

	if ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_DONT_USE_HASH ) != 'Y' ) {
		$page_url .= '#rsvpArea';
	}

	return $page_url;
}

function rsvp_pro_humanize_rsvp_status( $rsvp_status, $event_id = 0 ) {
	if ( strtolower( $rsvp_status ) === 'noresponse' ) {
		$text = rsvp_pro_get_frontend_string( 'noresponse_text' );
		if ( ( $event_id > 0 ) && ( rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_NO_RESPONSE_TEXT ) !== '' ) ) {
			$text = rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_NO_RESPONSE_TEXT );
		}

		return $text;
	} elseif ( strtolower( $rsvp_status ) === 'yes' ) {
		$text = rsvp_pro_get_frontend_string( 'yes_text' );

		if ( ( $event_id > 0 ) && ( rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_YES_TEXT ) !== '' ) ) {
			$text = rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_YES_TEXT );
		}

		return $text;
	} elseif ( strtolower( $rsvp_status ) === 'no' ) {
		$text = rsvp_pro_get_frontend_string( 'no_text' );

		if ( ( $event_id > 0 ) && ( rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_NO_TEXT ) !== '' ) ) {
			$text = rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_NO_TEXT );
		}

		return $text;
	} elseif ( strtolower( $rsvp_status ) === 'waitlist' ) {
		$text = rsvp_pro_get_frontend_string( 'waitlist_text' );

		if ( ( $event_id > 0 ) && ( rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_WAITLIST_FRIENDLY_TEXT ) !== '' ) ) {
			$text = rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_WAITLIST_FRIENDLY_TEXT );
		}

		return $text;
	} elseif ( strtolower( $rsvp_status ) === 'maybe' ) {
		$text = rsvp_pro_get_frontend_string( 'maybe_text' );

		if ( ( $event_id > 0 ) && ( rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_MAYBE_TEXT ) !== '' ) ) {
			$text = rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_MAYBE_TEXT );
		}

		return $text;
	} elseif ( strtolower( $rsvp_status ) === 'plusone' ) {
		$text = rsvp_pro_get_frontend_string( 'plusone_text' );

		if ( ( $event_id > 0 ) && ( rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_YES_PLUS_ONE_TEXT ) !== '' ) ) {
			$text = rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_YES_PLUS_ONE_TEXT );
		}

		return $text;
	}

	return $rsvp_status;
}

/**
 * Takes the RSVP status and translates it from the database stored
 * value to what the web forms are expecting
 *
 * @param  string $rsvp_status The RSVP status stored in the database
 *
 * @return string              The RSVP status that is expected on the web form
 */
function rsvp_pro_translate_status_to_form_value( $rsvp_status ) {
	$tmp_status = strToUpper( $rsvp_status );
	if ( $tmp_status === 'YES' ) {
		return 'Y';
	} elseif ( $tmp_status === 'WAITLIST' ) {
		return 'W';
	} elseif ( $tmp_status === 'MAYBE' ) {
		return 'M';
	} elseif ( $tmp_status === 'NORESPONSE' ) {
		return 'NoResponse';
	} elseif ( $tmp_status === 'PLUSONE' ) {
		return 'P';
	} else {
		return 'N';
	}
}

/**
 * Takes the form value for the RSVP status and translates it to the
 * expected value for the database.
 *
 * @param  string $form_value The form value that was submitted by the user
 *
 * @return string             The corresponding RSVP database value
 */
function rsvp_pro_translate_form_value_to_status( $form_value ) {
	$tmp_value = strtoupper( $form_value );

	if ( $tmp_value == 'Y' ) {
		return 'Yes';
	} elseif ( $tmp_value == 'W' ) {
		return 'Waitlist';
	} elseif ( $tmp_value == 'M' ) {
		return 'Maybe';
	} elseif ( $tmp_value == 'NORESPONSE' ) {
		return 'NoResponse';
	} elseif ( $tmp_value === 'PLUSONE' ) {
		return 'PlusOne';
	} else {
		return 'No';
	}
}

function rsvp_pro_get_event_status( $rsvpStatus, $eventId, $isSubEvent ) {
	$function = 'rsvp_pro_get_event_option';

	if ( $isSubEvent ) {
		$function = 'rsvp_pro_get_sub_event_option';
	}

	if ( strtolower( $rsvpStatus ) == 'yes' ) {
		$tmp = $function( $eventId, RSVP_PRO_OPTION_YES_VERBIAGE );
		if ( empty( $tmp ) ) {
			$tmp = rsvp_pro_humanize_rsvp_status( $rsvpStatus );
		}

		return $tmp;
	} elseif ( strtolower( $rsvpStatus ) == 'no' ) {
		$tmp = $function( $eventId, RSVP_PRO_OPTION_NO_VERBIAGE );
		if ( empty( $tmp ) ) {
			$tmp = rsvp_pro_humanize_rsvp_status( $rsvpStatus );
		}

		return $tmp;
	} elseif ( strtolower( $rsvpStatus ) == 'maybe' ) {
		$tmp = $function( $eventId, RSVP_PRO_OPTION_MAYBE_VERBIAGE );
		if ( empty( $tmp ) ) {
			$tmp = rsvp_pro_humanize_rsvp_status( $rsvpStatus );
		}

		return $tmp;
	} elseif ( strtolower( $rsvpStatus ) === 'plusone' ) {
		$tmp = $function( $eventId, RSVP_PRO_OPTION_PLUS_ONE_LABEL );

		if ( empty( $tmp ) ) {
			$tmp = rsvp_pro_humanize_rsvp_status( $rsvpStatus );
		}

		return $tmp;
	}

	return rsvp_pro_humanize_rsvp_status( $rsvpStatus );
}

/**
 * Formats the RSVP status so it matches up with how the enums have the
 * RSVP status. This is used because in certain database setups the enums
 * are case sensitive which can cause statuses not to be saved.
 *
 * @param  string $status The current RSVP status
 *
 * @return string         A correctly formatted RSVP status for the database
 */
function rsvp_pro_format_rsvp_status_for_database( $status ) {
	$formatted_status = $status;
	$tmp_status       = strtolower( $status );

	if ( $tmp_status == 'noresponse' ) {
		$tmp_status = 'NoResponse';
	} elseif ( $tmp_status == 'yes' ) {
		$tmp_status = 'Yes';
	} elseif ( $tmp_status == 'no' ) {
		$tmp_status = 'No';
	} elseif ( $tmp_status === 'waitlist' ) {
		$tmp_status = 'Waitlist';
	} elseif ( $tmp_status === 'maybe' ) {
		$tmp_status = 'Maybe';
	} elseif ( $tmp_status === 'plusone' ) {
		$tmp_status = 'PlusOne';
	}

	return $tmp_status;
}

function rsvp_pro_get_salutation_options( $rsvpId ) {
	$salutations = rsvp_pro_get_event_option( $rsvpId, RSVP_PRO_OPTION_SALUTATIONS );
	if ( empty( $salutations ) ) {
		$salutations = RSVP_PRO_DEFAULT_SALUTATION;
	}
	$salutations = explode( '||', $salutations );

	return $salutations;
}

function rsvp_pro_is_sub_or_parent_event( $rsvpId ) {
	global $wpdb;

	$sql   = 'SELECT COUNT(*) FROM ' . PRO_EVENT_TABLE . ' WHERE parentEventID = %d OR (id = %d AND parentEventID > 0)';
	$count = $wpdb->get_var( $wpdb->prepare( $sql, $rsvpId, $rsvpId ) );
	if ( $count > 0 ) {
		return true;
	} else {
		return false;
	}
}

function rsvp_pro_is_sub_event( $rsvpId ) {
	global $wpdb;

	$sql   = 'SELECT COUNT(*) FROM ' . PRO_EVENT_TABLE . ' WHERE id = %d AND parentEventID > 0';
	$count = $wpdb->get_var( $wpdb->prepare( $sql, $rsvpId ) );
	if ( $count > 0 ) {
		return true;
	} else {
		return false;
	}
}

function rsvp_pro_is_parent_event( $rsvpId ) {
	global $wpdb;

	$sql   = 'SELECT COUNT(*) FROM ' . PRO_EVENT_TABLE . ' WHERE parentEventID = %d OR (id = %d AND IFNULL(parentEventID, 0) = 0)';
	$count = $wpdb->get_var( $wpdb->prepare( $sql, $rsvpId, $rsvpId ) );

	if ( $count > 0 ) {
		return true;
	} else {
		return false;
	}
}

function rsvp_pro_event_access_type( $rsvpId ) {
	global $wpdb;
	$accessType = RSVP_PRO_OPEN_EVENT_ACCESS;

	$tmpAccessType = $wpdb->get_var( $wpdb->prepare( 'SELECT event_access FROM ' . PRO_EVENT_TABLE . ' WHERE id = %d', $rsvpId ) );
	if ( $tmpAccessType == RSVP_PRO_PRIVATE_EVENT_ACCESS ) {
		$accessType = RSVP_PRO_PRIVATE_EVENT_ACCESS;
	}

	return $accessType;
}

function does_user_have_access_to_event( $rsvpId, $attendeeId ) {
	global $wpdb;
	$haveAccess = false;

	$accessType = rsvp_pro_event_access_type( $rsvpId );
	if ( $accessType == RSVP_PRO_OPEN_EVENT_ACCESS ) {
		$haveAccess = true;
	} else {
		// Select access does the person have access?
		$uid = $wpdb->get_var(
			$wpdb->prepare(
				'SELECT rsvpAttendeeID FROM ' . PRO_EVENT_ATTENDEE_TABLE . ' WHERE rsvpAttendeeID = %d AND rsvpEventID = %d',
				$attendeeId,
				$rsvpId
			)
		);
		if ( $uid > 0 ) {
			$haveAccess = true;
		}
	}

	return $haveAccess;
}

/**
 * Checks to see if a user or an associated user has access to a given event.
 *
 * @param  int $rsvp_id     The event we want to see if the user has access to.
 * @param  int $attendee_id The attendee ID we want to check access on.
 * @return bool             If the user or associated attendees have access or not.
 */
function rsvp_pro_does_user_or_associated_users_have_access_to_event( $rsvp_id, $attendee_id ) {
	global $wpdb;
	$have_access = false;

	$access_type = rsvp_pro_event_access_type( $rsvp_id );
	if ( $access_type == RSVP_PRO_OPEN_EVENT_ACCESS ) {
		$have_access = true;
	} else {
		// Select access does the person have access?
		$assocs   = rsvp_pro_get_associated_attendees( $rsvp_id, $attendee_id );
		$assocs[] = $attendee_id;
		$count    = $wpdb->get_var(
			$wpdb->prepare(
				'SELECT count(rsvpAttendeeID) FROM ' . PRO_EVENT_ATTENDEE_TABLE . ' WHERE rsvpAttendeeID IN (' . esc_sql( implode( ',', $assocs ) ) . ') AND rsvpEventID = %d',
				$rsvp_id
			)
		);
		if ( $count > 0 ) {
			$have_access = true;
		}
	}

	return $have_access;
}

/**
 * Checks to see if a given attendee has access to the event passed in or any of the sub-events
 * below it.
 *
 * @param  int $event_id    The event ID we want to check to see if we have access to.
 * @param  int $attendee_id The attendee ID we want to check has access.
 * @return bool              true if the user has access, false otherwise.
 */
function rsvp_pro_does_user_have_access_to_event_or_subevents( $event_id, $attendee_id ) {
	global $wpdb;
	$has_access   = false;
	$open_accesses = array();

	$sql          = 'SELECT event_access, id FROM ' . PRO_EVENT_TABLE . ' WHERE id = %d OR parentEventID = %d';
	$access_types = $wpdb->get_results( $wpdb->prepare( $sql, $event_id, $event_id ) );
	foreach ( $access_types as $at ) {
		if ( ( RSVP_PRO_OPEN_EVENT_ACCESS === $at->event_access ) || ( '' === $at->event_access ) ) {
			$open_accesses[] = $at->id;
		}
	}

	if ( count( $open_accesses ) > 0 ) {
		$has_access = true;
	} else {
		$sql = 'SELECT rsvpAttendeeID FROM ' . PRO_EVENT_ATTENDEE_TABLE . ' 
		WHERE rsvpAttendeeID = %d AND rsvpEventID IN (SELECT id FROM ' . PRO_EVENT_TABLE . ' WHERE id = %d OR parentEventID = %d)';

		$access_to = $wpdb->get_results( $wpdb->prepare( $sql, $attendee_id, $event_id, $event_id ) );
		if ( count( $access_to ) > 0 ) {
			$has_access = true;
		}
	}

	return $has_access;
}

/**
 * Gets the event name.
 *
 * @param  int $event_id The event ID we want the name for.
 * @return string           The name of the event.
 */
function rsvp_pro_get_event_name( $event_id ) {
	return rsvp_pro_get_event_information( $event_id, RSVP_PRO_INFO_EVENT_NAME );
}

/**
 * Gets the event start date.
 *
 * @param  int $event_id The event ID we want the start date for.
 * @return string           The start date of the event.
 */
function rsvp_pro_get_event_start_date( $event_id ) {
	return rsvp_pro_get_event_information( $event_id, RSVP_PRO_INFO_EVENT_START_DATE );
}

/**
 * Gets the event end date.
 *
 * @param  int $event_id The event ID we want the end date for.
 * @return string        The event end date.
 */
function rsvp_pro_get_event_end_date( $event_id ) {
	return rsvp_pro_get_event_information( $event_id, RSVP_PRO_INFO_EVENT_END_DATE );
}

/**
 * Gets the event location.
 *
 * @param  int $event_id The event ID that we want the location for.
 * @return string        The event location informaion.
 */
function rsvp_pro_get_event_location( $event_id ) {
	return rsvp_pro_get_event_information( $event_id, RSVP_PRO_INFO_LOCATION );
}

/**
 * Gets the event description.
 *
 * @param  int $event_id The event ID we want the description for.
 * @return string        The event description.
 */
function rsvp_pro_get_event_description( $event_id ) {
	return rsvp_pro_get_event_information( $event_id, RSVP_PRO_INFO_DESCRIPTION );
}

/**
 * Gets the list of columns that should be displayed in the admin attendee list
 *
 * @param  int $event_id The event ID we want to get the columns for
 *
 * @return array            The array of attendee list columns that should be displayed
 */
function rsvp_pro_get_attendee_list_columns( $event_id ) {
	$attendee_list_columns = rsvp_pro_get_event_information( $event_id, RSVP_PRO_INFO_ATTENDEE_LIST_COLUMNS );

	if ( ! is_array( $attendee_list_columns ) || ( count( $attendee_list_columns ) == 0 ) ) {
		$attendee_list_columns = rsvp_pro_default_attendee_list_columns( $event_id );
	}

	return $attendee_list_columns;
}

function get_number_additional( $rsvp_id, $attendee = null ) {
	$num_guests = 3;
	if ( rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_NUM_ADDITIONAL_GUESTS ) != '' ) {
		$num_guests = rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_NUM_ADDITIONAL_GUESTS );
		if ( ! is_numeric( $num_guests ) || ( $num_guests < 0 ) ) {
			$num_guests = 3;
		}
	}

	if ( ( null !== $attendee ) && is_a( $attendee, 'Rsvp_Pro_Attendee' ) && ( $attendee->get_num_guests() >= 0 ) ) {
		$num_guests = $attendee->get_num_guests();
	} elseif ( ( $attendee != null ) && is_numeric( $attendee->numGuests ) && ( ( $attendee->numGuests ) >= 0 ) ) {
		$num_guests = $attendee->numGuests;
	}

	return $num_guests;
}

function rsvp_pro_is_allowed_status( $tmpRsvp ) {
	$allowedStatuses = array( 'yes', 'no', 'noresponse', 'waitlist', 'maybe', 'plusone' );

	if ( in_array( strtolower( $tmpRsvp ), $allowedStatuses ) ) {
		return true;
	}

	return false;
}

function rsvp_is_addslashes_enabled() {
	return get_magic_quotes_gpc();
}

function rsvp_pro_is_network_activated() {

	// Makes sure the plugin is defined before trying to use it
	if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
		require_once ABSPATH . '/wp-admin/includes/plugin.php';
	}

	return is_plugin_active_for_network( 'rsvp-pro-plugin/rsvp-pro.php' );
}

/**
 * Gets the associated attendee IDs for a given attendee.
 *
 * @param  int $rsvp_id     The event ID we want to get the associated attendees for.
 * @param  int $attendee_id The attendee ID we want to get the associated attendees for.
 * @return array            An array of IDs.
 */
function rsvp_pro_get_associated_attendees( $rsvp_id, $attendee_id ) {
	global $wpdb;
	$assoc = array();

	if ( rsvp_pro_is_sub_event( $rsvp_id ) ) {
		$rsvp_id = rsvp_pro_get_parent_event_id( $rsvp_id );
	}

	$sql = 'SELECT a.id
	        FROM ' . PRO_ATTENDEES_TABLE . ' a
			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) OR
	  		a.id IN (SELECT waa1.attendeeID FROM ' . PRO_ASSOCIATED_ATTENDEES_TABLE . ' waa1
	       	INNER JOIN ' . PRO_ASSOCIATED_ATTENDEES_TABLE . ' waa2 ON waa2.attendeeID = waa1.attendeeID  OR
	                                                 waa1.associatedAttendeeID = waa2.attendeeID
	       	WHERE waa2.associatedAttendeeID = %d AND waa1.attendeeID <> %d)) AND ( (a.rsvpEventID = %d) ';

	if ( rsvp_pro_is_shared_attendee_list_enabled() ) {
		$sql .= ' OR (a.rsvpEventID = ' . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . ')';
	}

	$sql         .= ')';
	$associations = $wpdb->get_results( $wpdb->prepare( $sql, $rsvp_id, $attendee_id, $attendee_id, $attendee_id, $rsvp_id ) );
	foreach ( $associations as $a ) {
		$assoc[] = $a->id;
	}

	return $assoc;
}

function rsvp_pro_admin_user_has_access_to_settings( $rsvpId ) {
	global $current_user;

	// This is a hack but since this gets used in an environment where it
	// could be checking multiple events at the same time and by default rsvp_pro_get_event_option assumes
	// in the current context to only be looking at one main event
	$roles = rsvp_pro_get_sub_event_option( $rsvpId, RSVP_PRO_OPTION_ADMIN_ROLES );
	if ( current_user_can( 'manage_options' ) ) {
		return true;
	}

	if ( empty( $roles ) || ( count( $roles ) <= 0 ) ) {
		return true;
	} else {
		foreach ( $roles as $role ) {
			if ( in_array( strtolower( $role ), $current_user->roles ) ) {
				return true;
			}
		}

		return false;
	}

	return false;
}

/**
 * Handles converting text encodings for characters like umlauts that might be stored in different encodings
 *
 * @param  string $text The text we wish to handle the encoding against
 *
 * @return string       The converted text
 */
function rsvp_pro_handle_text_encoding( $text ) {
	if ( function_exists( 'mb_convert_encoding' ) && function_exists( 'mb_detect_encoding' ) ) {
		return mb_convert_encoding( $text, 'UTF-8', mb_detect_encoding( $text, 'UTF-8, ISO-8859-1', true ) );
	}

	return $text;
}

function rsvp_pro_handle_attendee_check_in( $rsvp_id, $attendee_id, $check_in_value ) {
	global $wpdb;

	if ( rsvp_pro_is_sub_event( $rsvp_id ) || (
			rsvp_pro_is_shared_attendee_list_enabled() && ( $rsvp_id != RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID )
			&& rsvp_pro_is_attendee_a_global_attendee( $attendee_id )
		) ) {
		$sql    = 'SELECT id FROM ' . PRO_ATTENDEE_SUB_EVENTS_TABLE . ' WHERE rsvpAttendeeID = %d AND rsvpEventID = %d';
		$row_id = $wpdb->get_var( $wpdb->prepare( $sql, $attendee_id, $rsvp_id ) );
		if ( $row_id ) {
			$wpdb->update(
				PRO_ATTENDEE_SUB_EVENTS_TABLE,
				array(
					'checked_in' => $check_in_value,
				),
				array( 'id' => $row_id ),
				array( '%s' ),
				array( '%d' )
			);
		} else {
			// Need to insert...
			$wpdb->insert(
				PRO_ATTENDEE_SUB_EVENTS_TABLE,
				array(
					'checked_in'     => $check_in_value,
					'rsvpEventID'    => $rsvp_id,
					'rsvpAttendeeID' => $attendee_id,
				),
				array( '%s', '%d', '%d' )
			);
		}
	} else {
		$wpdb->update(
			PRO_ATTENDEES_TABLE,
			array(
				'checked_in' => $check_in_value,
			),
			array( 'id' => $attendee_id ),
			array( '%s' ),
			array( '%d' )
		);
	}
}

/**
 * Gets the first page's permalink that the shortcode appears on.
 *
 * @param  int $rsvp_id The ID for the event we are trying to get the permalink for.
 *
 * @return string          The URL or an empty string if nothing is found.
 */
function rsvp_pro_get_event_permalink( $rsvp_id ) {
	$query_string = array(
		's'        => '[rsvppro id="' . $rsvp_id . '"]',
		'sentence' => 1,
	);

	$query     = new WP_Query( $query_string );
	$event_url = '';
	if ( $query->have_posts() ) {
		$query->the_post();
		$event_url = get_permalink();
	}
	wp_reset_postdata();

	$data = array(
		'rsvp_id'   => $rsvp_id,
		'event_url' => $event_url,
	);

	$tmp_event_url = apply_filters( 'rsvp_pro_get_event_url', $data );

	if ( ! is_array( $tmp_event_url ) && ! empty( $tmp_event_url ) ) {
		$event_url = $tmp_event_url;
	}

	return $event_url;
}

/**
 * This function checks to see if the custom question exists
 * for a given event. This is used for operations like importing when
 * a user is trying to import data in with random IDs.
 *
 * @param  int $question_id The custom question ID.
 * @param  int $event_id The event ID.
 *
 * @return boolean          If the custom question exists for the event
 */
function rsvp_pro_custom_question_exists( $question_id, $event_id ) {
	global $wpdb;

	$cq_id = $wpdb->get_var( $wpdb->prepare( 'SELECT id FROM ' . PRO_QUESTIONS_TABLE . ' WHERE id = %d AND rsvpEventID IN (SELECT id FROM ' . PRO_EVENT_TABLE . ' WHERE id = %d OR parentEventID = %d )', $question_id, $event_id, $event_id ) );
	if ( ( $cq_id != null ) && ( $cq_id == $question_id ) ) {
		return true;
	}

	return false;
}

function rsvp_pro_get_parent_event_id( $event_id ) {
	global $wpdb;

	$sql = 'SELECT parentEventID FROM ' . PRO_EVENT_TABLE . ' WHERE id = %d';

	return $wpdb->get_var( $wpdb->prepare( $sql, $event_id ) );
}

/**
 * Gets the RSVP counts for all the status types for a given event.
 *
 * @param  int $event_id The event ID we want to get the status types for
 *
 * @return array         An associated array of RSVP statuses
 */
function rsvp_pro_get_rsvp_counts( $event_id ) {
	global $wpdb;

	if ( rsvp_pro_is_sub_event( $event_id ) ) {

		$baseSql = 'SELECT COUNT(*)
    					FROM ' . PRO_ATTENDEES_TABLE . ' a
    					LEFT JOIN ' . PRO_ATTENDEE_SUB_EVENTS_TABLE . ' se ON se.rsvpAttendeeID = a.id AND a.rsvpEventID = %d
    					LEFT 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))) AND ';

		$rsvp_event_where = ' ( ( a.rsvpEventID = %d ) OR ( a.rsvpEventID = %d ) ';
		if ( rsvp_pro_is_shared_attendee_list_enabled() ) {
			$rsvp_event_where .= ' OR ( a.rsvpEventID = ' . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . ') ';
		}
		$rsvp_event_where .= ')';

		$sub_event_id    = $event_id;
		$parent_event_id = rsvp_pro_get_parent_event_id( $event_id );

		$yes_count = $wpdb->get_var( $wpdb->prepare( $baseSql . " (a.rsvpStatus = 'Yes' OR a.rsvpStatus = 'PlusOne') AND " . $rsvp_event_where, $sub_event_id, $sub_event_id, $parent_event_id ) );

		$plus_one_count = $wpdb->get_var( $wpdb->prepare( $baseSql . " a.rsvpStatus = 'PlusOne' AND " . $rsvp_event_where, $sub_event_id, $sub_event_id, $parent_event_id ) );

		$no_count = $wpdb->get_var( $wpdb->prepare( $baseSql . " a.rsvpStatus = 'No' AND " . $rsvp_event_where, $sub_event_id, $sub_event_id, $parent_event_id ) );

		$sql = $baseSql . " (a.rsvpStatus = 'NoResponse' OR a.rsvpStatus IS NULL) AND " . $rsvp_event_where;
		if ( rsvp_pro_get_event_information( $sub_event_id, RSVP_PRO_INFO_EVENT_ACCESS ) == RSVP_PRO_PRIVATE_EVENT_ACCESS ) {
			$sql = 'SELECT COUNT(*) FROM ' . PRO_EVENT_ATTENDEE_TABLE . ' ea
                LEFT JOIN ' . PRO_ATTENDEE_SUB_EVENTS_TABLE . ' se ON se.rsvpAttendeeID = ea.rsvpAttendeeID
                JOIN ' . PRO_ATTENDEES_TABLE . " a ON a.id = ea.rsvpAttendeeID
                WHERE (se.rsvpStatus IS NULL OR se.rsvpStatus = 'NoResponse') AND
                ea.rsvpEventID = %d AND " . $rsvp_event_where;
		}

		$no_response_count = $wpdb->get_var( $wpdb->prepare( $sql, $sub_event_id, $sub_event_id, $parent_event_id ) );
		$wait_list_count   = $wpdb->get_var( $wpdb->prepare( $baseSql . " a.rsvpStatus = 'Waitlist' AND " . $rsvp_event_where, $sub_event_id,$sub_event_id, $parent_event_id ) );

		$maybe_count = $wpdb->get_var( $wpdb->prepare( $baseSql . " a.rsvpStatus = 'Maybe' AND " . $rsvp_event_where, $sub_event_id,$sub_event_id, $parent_event_id ) );
	} else {
		$baseSql = '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_count         = $wpdb->get_var( $wpdb->prepare( $baseSql . " AND (rsvpStatus = 'Yes' OR rsvpStatus = 'PlusOne') AND rsvpEventID = %d", $event_id ) );
		$plus_one_count    = $wpdb->get_var( $wpdb->prepare( $baseSql . " AND rsvpStatus = 'PlusOne' AND rsvpEventID = %d", $event_id ) );
		$no_count          = $wpdb->get_var( $wpdb->prepare( $baseSql . " AND rsvpStatus = 'No' AND rsvpEventID = %d", $event_id ) );
		$no_response_count = $wpdb->get_var( $wpdb->prepare( $baseSql . " AND rsvpStatus = 'NoResponse' AND rsvpEventID = %d", $event_id ) );
		$wait_list_count   = $wpdb->get_var( $wpdb->prepare( $baseSql . " AND rsvpStatus = 'Waitlist' AND rsvpEventID = %d", $event_id ) );
		$maybe_count       = $wpdb->get_var( $wpdb->prepare( $baseSql . " AND rsvpStatus = 'Maybe' AND rsvpEventID = %d", $event_id ) );

		if ( rsvp_pro_is_shared_attendee_list_enabled() ) {
			$baseSql = 'SELECT COUNT(*) FROM ' . PRO_ATTENDEES_TABLE . ' a
                LEFT 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        = $baseSql . " (se.rsvpStatus = 'Yes' or se.rsvpStatus = 'PlusOne')";
			$yes_count += $wpdb->get_var( $wpdb->prepare( $sql, $event_id ) );

			$sql             = $baseSql . " se.rsvpStatus = 'PlusOne' ";
			$plus_one_count += $wpdb->get_var( $wpdb->prepare( $sql, $event_id ) );

			$sql       = $baseSql . " se.rsvpStatus = 'No'";
			$no_count += $wpdb->get_var( $wpdb->prepare( $sql, $event_id ) );

			$sql               = $baseSql . " (((a.rsvpStatus = 'NoResponse' OR a.rsvpStatus IS NULL) AND a.rsvpEventID = %d) OR ( (se.rsvpStatus = 'NoResponse' OR se.rsvpStatus IS NULL) AND a.rsvpEventID = " . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . ' ) ) ';
			$no_response_count = $wpdb->get_var( $wpdb->prepare( $sql, $event_id, $event_id ) );

			$sql              = $baseSql . " se.rsvpStatus = 'Waitlist'";
			$wait_list_count += $wpdb->get_var( $wpdb->prepare( $sql, $event_id ) );

			$sql          = $baseSql . " se.rsvpStatus = 'Maybe'";
			$maybe_count += $wpdb->get_var( $wpdb->prepare( $sql, $event_id ) );
		}
	}

	$results = array(
		'yes'         => $yes_count,
		'no'          => $no_count,
		'no_response' => $no_response_count,
		'wait_list'   => $wait_list_count,
		'maybe'       => $maybe_count,
		'plus_one'    => $plus_one_count,
	);

	return $results;
}

/**
 * Gets a string for the admin-end area of the RSVP plugin. If the
 * string key is found it or a translated string will be returned.
 *
 * @param  string $string_key Name of key that is associated with the string
 *
 * @return string             The string that should be returned
 */
function rsvp_pro_get_admin_string( $string_key ) {
	global $admin_strings;
	global $us_admin_strings;

	if ( $admin_strings == null ) {
		$admin_strings = rsvp_pro_get_admin_strings();
	}

	$string = '';

	if ( key_exists( $string_key, $admin_strings ) ) {
		// Set locale to english so we can get the original string to try and see if a
		// translation has been set by PolyLang. If not then revert and return original string.
		$new_string = '';

		if ( isset( $us_admin_strings[ $string_key ]['text'] ) ) {
			$new_string = $us_admin_strings[ $string_key ]['text'];
		}

		$string     = rsvp_pro_get_translated_string( $new_string );
		if ( $string == $new_string ) {
			$string = $admin_strings[ $string_key ]['text'];
		}
	}

	return $string;
}

/**
 * Gets a string for the front-end area of the RSVP plugin. If the
 * string key is found it or a translated string will be returned.
 *
 * @param  string $string_key Name of key that is associated with the string.
 *
 * @return string             The string that should be returned.
 */
function rsvp_pro_get_frontend_string( $string_key ) {
	global $rsvp_pro_frontend_strings;
	global $us_rsvp_pro_frontend_strings;
	$string = '';
	if ( null === $rsvp_pro_frontend_strings ) {
		$rsvp_pro_frontend_strings = rsvp_pro_get_frontend_strings();
	}

	if ( array_key_exists( $string_key, $rsvp_pro_frontend_strings ) ) {
		$new_string = isset($us_rsvp_pro_frontend_strings[ $string_key ]['text']) ? $us_rsvp_pro_frontend_strings[ $string_key ]['text'] : '';
		$string     = rsvp_pro_get_translated_string( $new_string );
		if ( $string === $new_string ) {
			$string = $rsvp_pro_frontend_strings[ $string_key ]['text'];
		}
	}

	return $string;
}

/**
 * Gets the translated string. Does checks to see if the translation functions exist if
 * not then no translation occurs. We don't need to worry when it is WPML as they
 * have automagic voodoo which doesn't require us to retrieve it.
 *
 * @param  string $string The string we want translated
 *
 * @return string         Either the original string or the translated string.
 */
function rsvp_pro_get_translated_string( $string ) {
	$text = $string;
	if ( function_exists( 'pll__' ) ) {
		$text = pll__( $string );
	}

	return $text;
}

/**
 * Tries to get a translated string for a dynamic property like custom
 * questions for a given event.
 *
 * @param  string $key_name The translation key name we are trying to retrieve.
 * @param  string $string The current string we are trying to retrieve a translation for.
 * @param  int    $event_id The current event ID.
 *
 * @return string           The translated text or the original text if no translation exists.
 */
function rsvp_pro_get_dynamic_translated_string( $key_name, $string, $event_id ) {
	$text = $string;

	if ( function_exists( 'pll__' ) ) {
		$text = pll__( $string );
	}

	if ( has_filter( 'wpml_translate_string' ) ) {
		$event_name = rsvp_pro_get_event_name( $event_id );
		$package    = array(
			'kind'  => "RSVPPro - {$event_id}",
			'name'  => "rsvp-pro-plugin-{$event_id}",
			'title' => "RSVP Pro Plugin - {$event_name}",
		);
		$key_name   = strtolower( $key_name );
		$key_name   = str_replace( ' ', '-', $key_name );
		$text       = apply_filters( 'wpml_translate_string', $string, $key_name, $package );
	}

	return $text;
}

/**
 * Checks to see if the global attendee list is enabled or not
 *
 * @return boolean True if the attendee list is enabled, false otherwise
 */
function rsvp_pro_is_shared_attendee_list_enabled() {
	return ( get_option( RSVP_PRO_GLOBAL_ENABLE_GLOBAL_ATTENDEE_LIST ) === 'Y' ) ? true : false;
}

/**
 * Checks to see if the change log functionality is turned on.
 *
 * @return boolean True if the change log is enabled, false otherwise.
 */
function rsvp_pro_is_change_log_enabled() {
	return ( 'Y' === get_option( RSVP_PRO_GLOBAL_OPTION_ENABLE_ATTENDEE_CHANGELOG ) ) ? true : false;
}

/**
 * This function checks to see if the user is part of the shared attendee list.
 *
 * @param  int $attendee_id The attendee ID we want to check to see if it is part of the shared attendee list
 *
 * @return bool               True if it is part of the shared attendee list, false otherwise
 */
function rsvp_pro_is_attendee_a_global_attendee( $attendee_id ) {
	global $wpdb;

	$sql    = 'SELECT id FROM ' . PRO_ATTENDEES_TABLE . ' WHERE id = %d AND rsvpEventID = %d';
	$tmp_id = $wpdb->get_var( $wpdb->prepare( $sql, $attendee_id, RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID ) );

	return ( $tmp_id != null ) ? true : false;
}

/**
 * Returns the default columns that should be shown on the attendee list admin area
 *
 * @param  int $event_id The event ID we are getting the default columns for
 *
 * @return array            The array of default columns for the event
 */
function rsvp_pro_default_attendee_list_columns( $event_id ) {
	global $wpdb;

	$columns = array(
		'attendee_name',
		'rsvp_status',
		'rsvp_date',
		'additional_attendee',
		'note',
		'associated_attendees',
	);

	$sql       = 'SELECT id FROM ' . PRO_QUESTIONS_TABLE . ' WHERE rsvpEventID = %d';
	$questions = $wpdb->get_results( $wpdb->prepare( $sql, $event_id ) );
	foreach ( $questions as $q ) {
		$columns[] = 'custom_question_' . $q->id;
	}

	return $columns;
}

/**
 * Replace a smart quote with an actual single-quote so that people can
 * find themselves when they do a search on the front-end.
 *
 * @param  string $in The string we want to replace smart-quotes with single-quotes.
 *
 * @return string     The string that has had the values replaced.
 */
function rsvp_pro_smart_quote_replace( $in ) {
	return str_replace( '’', '\'', $in );
}

/**
 * Validates the submitted captcha to make sure a person has been "verified."
 *
 * @param  string $code_supplied The captcha code to check.
 *
 * @return boolean               True if the captcha passes validation, false otherwise.
 */
function rsvp_pro_validate_recaptcha( $code_supplied ) {
	global $rsvp_id;

	$valid = false;

	$response = wp_remote_post(
		'https://www.google.com/recaptcha/api/siteverify',
		array(
			'method'   => 'POST',
			'blocking' => true,
			'body'     => array(
				'secret'   => rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_RECAPTCHA_SECRET_KEY ),
				'response' => $code_supplied,
			),
		)
	);

	if ( ! is_wp_error( $response ) ) {
		$google_response = json_decode( wp_remote_retrieve_body( $response ) );
		if ( true === $google_response->success ) {
			$valid = true;
		}
	}

	return $valid;
}

/**
 * Validates the submitted captcha to make sure a person has been "verified."
 *
 * @param  string $code_supplied The captcha code to check.
 *
 * @return boolean               True if the captcha passes validation, false otherwise.
 */
function rsvp_pro_validate_turnstile( $code_supplied ) {
	global $rsvp_id;

	$valid = false;

	$args = array(
		'body' => array(
			'secret'   => rsvp_pro_get_event_option( $rsvp_id, RSVP_PRO_OPTION_TURNSTILE_SECRET_KEY ),
			'response' => $code_supplied,
		),
	);

	$response = wp_remote_post( 'https://challenges.cloudflare.com/turnstile/v0/siteverify', $args );

	if ( ! is_wp_error( $response ) ) {
		$cloudflare_response = json_decode( wp_remote_retrieve_body( $response ) );
		if ( true === $cloudflare_response->success ) {
			$valid = true;
		}
	}

	return $valid;
}


/**
 * Generates the token used for attendees for auto-checking in an attendee via QR code.
 *
 * @return string The token used for checking in attendees.
 */
function rsvp_pro_generate_attendee_token() {
	return uniqid( '', true );
}

/**
 * Generates a QR code for attendee check-ins.
 *
 * @param  string $attendee_token The attendee token that should be used checking in.
 *
 * @return string                 The path for the file we wish to attach.
 */
function rsvp_pro_generate_qr_for_email( $attendee_token ) {
	$url       = site_url( '/' );
	$url       = add_query_arg( 'rsvp_pro_attendee', $attendee_token, $url );
	$file_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'qr_code_' . uniqid() . '.png';

	QRcode::png( $url, $file_path );

	return $file_path;
}

/**
 * Generates a prefill url QR Code for an attendee.
 *
 * @param  string $prefill_url The prefill URL for an attendee.
 * @param  string $token       The token associated with this attendee's QR code.
 * @return string              The path for the file we wish to attach.
 */
function rsvp_pro_generate_prefill_qr( $prefill_url, $token ) {
	$base_path = wp_upload_dir()['basedir'] . DIRECTORY_SEPARATOR . 'rsvp_pro';
	if ( false === is_dir( $base_path ) ) {
		mkdir( $base_path );
	}

	$file_path = $base_path . DIRECTORY_SEPARATOR . 'qr_' . $token . '.png';
	if ( file_exists( $file_path ) === false ) {
		QRcode::png( $prefill_url, $file_path );
	}

	return $file_path;
}

/**
 * Encodes an image as base64 for including inline.
 *
 * @param  string $file_path The file path we want to encode.
 *
 * @return string            The base64 encoded file contents OR false.
 */
function rsvp_pro_encode_image_as_base64( $file_path ) {
	if ( file_exists( $file_path ) ) {
		$type   = pathinfo( $file_path, PATHINFO_EXTENSION );
		$data   = file_get_contents( $file_path );
		$base64 = 'data:image/' . $type . ';base64,' . base64_encode( $data );

		return $base64;
	}

	return false;
}

/**
 * RSVP Pro wrapper for sending email. This is used to allow for
 * inline attachments, etc...
 *
 * @param string $email The email address we want to send the email to.
 * @param string $subject The subject for the email.
 * @param string $body The body of the email.
 * @param array  $headers The headers for the email.
 * @param array  $attachments The attachments for the email.
 */
function rsvp_pro_send_mail( $email, $subject, $body, $headers = '', $attachments = array() ) {
	global $rsvp_pro_inline_attachments;

	add_action(
		'phpmailer_init',
		function ( &$phpmailer ) use ( $rsvp_pro_inline_attachments ) {
			$phpmailer->SMTPKeepAlive = true;
			if ( is_array( $rsvp_pro_inline_attachments ) && ( 0 < count( $rsvp_pro_inline_attachments ) ) ) {
				foreach ( $rsvp_pro_inline_attachments as $a ) {
					$phpmailer->AddEmbeddedImage( $a['file'], $a['uid'], $a['name'] );
				}
			}
		}
	);
	wp_mail( $email, $subject, $body, $headers, $attachments );

	if ( is_array( $rsvp_pro_inline_attachments ) && ( 0 < count( $rsvp_pro_inline_attachments ) ) ) {
		foreach ( $rsvp_pro_inline_attachments as $a ) {
			if ( file_exists( $a['name'] ) ) {
				unlink( $a['name'] );
			}
		}
	}
	$rsvp_pro_inline_attachments = array();
}

/**
 * Gets a list of attendees for a given event.
 *
 * @param  int    $event_id         The event id we want to get attendees for.
 * @param  array  $select_attendees An array of ints that specifies only the attendees we want.
 * @param  string $rsvp_status      A way to specify only get attendees who have RSVP'd with a specific status.
 * @return array                    An array of attendees with the fields (id, firstName, lastName, rsvpStatus, note, passcode, etc...).
 */
function rsvp_pro_get_attendees( $event_id, $select_attendees = array(), $rsvp_status = '' ) {
	global $wpdb;

	$is_sub_event    = false;
	$parent_event_id = $wpdb->get_var( $wpdb->prepare( 'SELECT parentEventID FROM ' . PRO_EVENT_TABLE . ' WHERE id = %d', $event_id ) );
	if ( $parent_event_id > 0 ) {
		$is_sub_event = true;
		$sub_event_id = $event_id;
		$event_id     = $parent_event_id;
	}

	if ( $is_sub_event ) {
		$sql = "SELECT a.id, firstName, lastName, IFNULL(se.rsvpStatus, 'NoResponse') AS rsvpStatus,
					note, passcode, email, salutation, suffix, a.rsvpDate, se.token 
				FROM " . PRO_ATTENDEES_TABLE . ' a
				INNER JOIN ' . PRO_EVENT_TABLE . ' e ON e.id = %d
				LEFT JOIN ' . PRO_ATTENDEE_SUB_EVENTS_TABLE . ' se ON se.rsvpAttendeeID = a.id AND se.rsvpEventID = %d
				WHERE ( (a.rsvpEventID = %d) ';

		if ( rsvp_pro_is_shared_attendee_list_enabled() ) {
			$sql .= ' OR (a.rsvpEventID = ' . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . ') ';
		}

		$sql .= " ) AND email <> '' AND ((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)))';
	} else {
		$sql = 'SELECT a.id, firstName, lastName, IFNULL(se.rsvpStatus, a.rsvpStatus) AS rsvpStatus, 
				note, passcode, email, salutation, suffix, a.rsvpDate, a.token 
				FROM ' . PRO_ATTENDEES_TABLE . ' a
				INNER 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
				WHERE ( (a.rsvpEventID = %d)  ';

		if ( rsvp_pro_is_shared_attendee_list_enabled() ) {
			$sql .= ' OR (a.rsvpEventID = ' . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . ') ';
		}

		$sql .= " ) AND email <> '' AND ((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)))';
	}

	if ( ! empty( $rsvp_status ) ) {
		if ( $is_sub_event ) {
			if ( $rsvp_status === 'NoResponse' ) {
				$sql .= ' AND ( se.rsvpStatus = %s OR se.rsvpStatus IS NULL ) ';
			} else {
				$sql .= ' AND se.rsvpStatus = %s  ';
			}
		} else {
			if ( $rsvp_status === 'NoResponse' ) {
				$sql .= ' AND ( (a.rsvpStatus = %s AND a.rsvpEventID != ' . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . ') OR ( ( se.rsvpStatus = %s OR se.rsvpStatus IS NULL ) AND a.rsvpEventID = ' . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . ' ) ) ';
			} else {
				$sql .= ' AND ( (a.rsvpStatus = %s AND a.rsvpEventID != ' . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . ') OR (se.rsvpStatus = %s) ) ';	
			}
		}
	}

	if ( count( $select_attendees ) > 0 ) {
		$valid = true;
		// Make sure that all the attendee values passed in are numeric.
		foreach ( $select_attendees as $a ) {
			if ( ! is_numeric( $a ) || ( $a <= 0 ) ) {
				$valid = false;
			}
		}

		if ( $valid ) {
			$sql .= ' AND a.id IN (' . implode( ',', $select_attendees ) . ')';
		}
	}

	$sql .= ' ORDER BY a.lastName, a.firstName ';

	if ( $is_sub_event ) {
		if ( ! empty( $rsvp_status ) ) {
			$prepared_sql = $wpdb->prepare( $sql, $sub_event_id, $sub_event_id, $event_id, $rsvp_status );
		} else {
			$prepared_sql = $wpdb->prepare( $sql, $sub_event_id, $sub_event_id, $event_id );
		}
	} else {
		if ( ! empty( $rsvp_status ) ) {
			$prepared_sql = $wpdb->prepare( $sql, $event_id, $event_id, $rsvp_status, $rsvp_status );
		} else {
			$prepared_sql = $wpdb->prepare( $sql, $event_id, $event_id );
		}
	}

	return $wpdb->get_results( $prepared_sql );
}

/**
 * Calculates the total amount due for an attendee and their related attendees. This function
 * assumes you have already saved the information to the database and it is the most up to date
 * information for this attendee.
 *
 * @param  int               $event_id    The event ID we want to calculate the price for.
 * @param  Rsvp_Pro_Attendee $attendee    The attendee object we want to calculate the price for.
 * @return array             An array holding the total, and then the total broken out by attendee and each event
 */
function rsvp_pro_existing_attendee_calculate_total_due( $event_id, $attendee ) {
	global $wpdb;
	$total_due = 0;
	$totals    = array( 'total' => 0, 'attendee_totals' => array() );

	if ( 'Y' === rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_ENABLE_PAYMENTS ) ) {
		$price           = rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_TICKET_PRICE );
		$event_record    = rsvp_pro_get_attendee_event_record( $event_id, $attendee->get_id() );
		$attendee_totals = array();

		if ( $event_record->get_payment_status() !== RSVP_PRO_PAID_STATUS ) {
			if ( ( $event_record->get_rsvp_status() === 'Yes' ) || ( 'Maybe' === $event_record->get_rsvp_status() ) ) {
				$total_due                   += $price;
				$attendee_totals[ $event_id ] = $price;
			} elseif ( 'PlusOne' === $event_record->get_rsvp_status() ) {
				$total_due                   += ( $price * 2 );
				$attendee_totals[ $event_id ] = ( $price * 2 );
			}
		}

		if ( rsvp_pro_is_parent_event( $event_id ) ) {
			$sql        = 'SELECT payment_status, amount, rsvpStatus, rsvpEventID  
			FROM ' . PRO_ATTENDEE_SUB_EVENTS_TABLE . ' 
			WHERE rsvpAttendeeID = %d AND rsvpEventID IN ( SELECT id FROM ' . PRO_EVENT_TABLE . ' WHERE parentEventID = %d )';
			$sub_events = $wpdb->get_results( $wpdb->prepare( $sql, $attendee->get_id(), $event_id ) );
			foreach ( $sub_events as $se ) {
				$ticket_price = rsvp_pro_get_event_option( $se->rsvpEventID, RSVP_PRO_OPTION_TICKET_PRICE );
				if ( ( $se->payment_status !== RSVP_PRO_PAID_STATUS ) && ( $ticket_price > 0 ) ) {
					if ( ( 'Yes' === $se->rsvpStatus ) || ( 'Maybe' === $se->rsvpStatus ) ) {
						$total_due                          += $ticket_price;
						$attendee_totals[ $se->rsvpEventID ] = $ticket_price;
					} elseif ( 'PlusOne' === $se->rsvpStatus ) {
						$total_due                          += ( $ticket_price * 2 );
						$attendee_totals[ $se->rsvpEventID ] = ( $ticket_price * 2 );
					}
				}
			}
		}
		$totals['attendee_totals'][ $attendee->get_id() ] = $attendee_totals;

		$sql = 'SELECT id, firstName, lastName, email, personalGreeting, 
		rsvpStatus, salutation, suffix, passcode FROM ' . PRO_ATTENDEES_TABLE . '
		WHERE (id IN (SELECT attendeeID FROM ' . PRO_ASSOCIATED_ATTENDEES_TABLE . ' WHERE associatedAttendeeID = %d)
		OR id in (SELECT associatedAttendeeID FROM ' . PRO_ASSOCIATED_ATTENDEES_TABLE . ' WHERE attendeeID = %d) OR
		id IN (SELECT waa1.attendeeID FROM ' . PRO_ASSOCIATED_ATTENDEES_TABLE . ' waa1
		INNER JOIN ' . PRO_ASSOCIATED_ATTENDEES_TABLE . ' waa2 ON waa2.attendeeID = waa1.attendeeID  OR
		waa1.associatedAttendeeID = waa2.attendeeID
		WHERE waa2.associatedAttendeeID = %d AND waa1.attendeeID <> %d)) AND ( (rsvpEventID = %d) ';

		if ( rsvp_pro_is_shared_attendee_list_enabled() ) {
			$sql .= ' OR (rsvpEventID = ' . RSVP_PRO_GLOBAL_ATTENDEE_EVENT_ID . ')';
		}

		$sql .= ')';

		$associations = $wpdb->get_results(
			$wpdb->prepare(
				$sql,
				$attendee->get_id(),
				$attendee->get_id(),
				$attendee->get_id(),
				$attendee->get_id(),
				$event_id
			)
		);

		foreach ( $associations as $assoc ) {
			$attendee_totals = array();
			$event_record    = rsvp_pro_get_attendee_event_record( $event_id, $assoc->id );

			if ( $event_record->get_payment_status() !== RSVP_PRO_PAID_STATUS ) {
				if ( ( $event_record->get_rsvp_status() === 'Yes' ) || ( 'Maybe' === $event_record->get_rsvp_status() ) ) {
					$total_due += $price;
					$attendee_totals[ $event_id ] = $price;
				} elseif ( 'PlusOne' === $event_record->get_rsvp_status() ) {
					$total_due += ( $price * 2 );
					$attendee_totals[ $event_id ] = ( $price * 2 );
				}
			}

			if ( rsvp_pro_is_parent_event( $event_id ) ) {
				$sql        = 'SELECT payment_status, amount, rsvpStatus, rsvpEventID  
				FROM ' . PRO_ATTENDEE_SUB_EVENTS_TABLE . ' 
				WHERE rsvpAttendeeID = %d AND rsvpEventID IN ( SELECT id FROM ' . PRO_EVENT_TABLE . ' WHERE parentEventID = %d )';
				$sub_events = $wpdb->get_results( $wpdb->prepare( $sql, $assoc->id, $event_id ) );
				foreach ( $sub_events as $se ) {
					$ticket_price = rsvp_pro_get_event_option( $se->rsvpEventID, RSVP_PRO_OPTION_TICKET_PRICE );
					if ( ( $se->payment_status !== RSVP_PRO_PAID_STATUS ) && ( $ticket_price > 0 ) ) {
						if ( ( 'Yes' === $se->rsvpStatus ) || ( 'Maybe' === $se->rsvpStatus ) ) {
							$total_due += $ticket_price;
							$attendee_totals[ $se->rsvpEventID ] = ( $ticket_price * 2 );
						} elseif ( 'PlusOne' === $se->rsvpStatus ) {
							$total_due += ( $ticket_price * 2 );
							$attendee_totals[ $se->rsvpEventID ] = ( $ticket_price * 2 );
						}
					}
				}
			}
			$totals['attendee_totals'][ $assoc->id ] = $attendee_totals;
		}

		$totals['total'] = rsvp_pro_format_money( $total_due, $event_id );
	}

	return $totals;
}

function rsvp_pro_get_total_paid_for_event( $event_id ) {
	global $wpdb;

	$sql = 'SELECT SUM(ae.amount) as total FROM ' . PRO_ATTENDEE_EVENT_COSTS_TABLE . ' ae 
	JOIN ' . PRO_ATTENDEES_TABLE . ' a ON a.rsvpEventID = ae.rsvpEventID 
	WHERE a.payment_status = %s AND ae.rsvpEventID = %d 
	UNION 
	SELECT SUM(ae.AMOUNT) as total FROM ' . PRO_ATTENDEE_EVENT_COSTS_TABLE . ' ae 
	JOIN ' . PRO_ATTENDEE_SUB_EVENTS_TABLE . ' se ON se.rsvpEventID = ae.rsvpEventID 
	WHERE se.payment_status = %s AND ae.rsvpEventID = %d';

	$amounts = $wpdb->get_results( $wpdb->prepare( $sql, RSVP_PRO_PAID_STATUS, $event_id, RSVP_PRO_PAID_STATUS, $event_id ) );
	$total   = 0;
	foreach ( $amounts as $a ) {
		$total += $a->total;
	}

	return rsvp_pro_format_money( $total, $event_id );
}

/**
 * Formats an amount to match with what the user has configured for the event.
 *
 * @param  string $amount   The amount we want formatted.
 * @param  int    $event_id The event ID we want to grab the options from.
 * @return string           The amount formatted based on the event options.
 */
function rsvp_pro_format_money( $amount, $event_id ) {
	$formatted_amount = $amount;

	$comma_separator   = ',';
	$decimal_separator = '.';

	if ( '' !== rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_THOUSANDS_SEPARATOR ) ) {
		$comma_separator = rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_THOUSANDS_SEPARATOR );
	}

	if ( '' !== rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_DECIMAL_SEPARATOR ) ) {
		$decimal_separator = rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_DECIMAL_SEPARATOR );
	}
	$formatted_amount = number_format( $formatted_amount, 2, $decimal_separator, $comma_separator );

	return $formatted_amount;
}

/**
 * Gets an attendee's event record for the specified event ID.
 *
 * @param  int $event_id    The event ID we want to get the record for.
 * @param  int $attendee_id The attendee we want the event record ID for.
 * @return objects          Either an instance of Rsvp_Pro_Attendee or Rsvp_Pro_Attendee_Subevent.
 */
function rsvp_pro_get_attendee_event_record( $event_id, $attendee_id ) {
	$event_record = new Rsvp_Pro_Attendee( $attendee_id );
	if ( $event_id != $event_record->get_rsvp_event_id() ) {
		$main_event_record = $event_record;
		$event_record      = new Rsvp_Pro_Attendee_Subevent();
		foreach ( $main_event_record->get_sub_event_responses() as $se ) {
			if ( $se->get_event_id() === $event_id ) {
				$event_record = $se;
				break;
			}
		}
	}

	return $event_record;
}

/**
 * Holds a static list of currencies that the plugin supports for charging.
 *
 * @return array An array of currencies.
 */
function rsvp_pro_get_currencies() {
	$currencies = array(
		array(
			'name'   => 'Australian dollar',
			'code'   => 'AUD',
			'symbol' => '$',
		),
		array(
			'name'   => 'Canadian dollar',
			'code'   => 'CAD',
			'symbol' => '$',
		),
		array(
			'name'   => 'Czech koruna',
			'code'   => 'CZK',
			'symbol' => 'Kč',
		),
		array(
			'name'   => 'Danish krone',
			'code'   => 'DKK',
			'symbol' => 'kr.',
		),
		array(
			'name'   => 'Euro',
			'code'   => 'EUR',
			'symbol' => '€',
		),
		array(
			'name'   => 'Hong Kong dollar',
			'code'   => 'HKD',
			'symbol' => '$',
		),
		array(
			'name'   => 'Israeli new shekel',
			'code'   => 'ILS',
			'symbol' => '₪',
		),
		array(
			'name'   => 'Mexican peso',
			'code'   => 'MXN',
			'symbol' => '$',
		),
		array(
			'name'   => 'New Zealand dollar',
			'code'   => 'NZD',
			'symbol' => '$',
		),
		array(
			'name'   => 'Norwegian krone',
			'code'   => 'NOK',
			'symbol' => 'kr',
		),
		array(
			'name'   => 'Philippine peso',
			'code'   => 'PHP',
			'symbol' => '₱',
		),
		array(
			'name'   => 'Polish złoty',
			'code'   => 'PLN',
			'symbol' => 'zł',
		),
		array(
			'name'   => 'Pound sterling',
			'code'   => 'GBP',
			'symbol' => '£',
		),
		array(
			'name'   => 'Russian ruble',
			'code'   => 'RUB',
			'symbol' => '₽',
		),
		array(
			'name'   => 'Singapore dollar',
			'code'   => 'SGD',
			'symbol' => '$',
		),
		array(
			'name'   => 'Swedish krona',
			'code'   => 'SEK',
			'symbol' => 'kr',
		),
		array(
			'name'   => 'Swiss franc',
			'code'   => 'CHF',
			'symbol' => 'CHF',
		),
		array(
			'name'   => 'Thai baht',
			'code'   => 'THB',
			'symbol' => '฿',
		),
		array(
			'name'   => 'United States dollar',
			'code'   => 'USD',
			'symbol' => '$',
		),
	);

	return $currencies;
}

function rsvp_pro_get_event_currency_symbol( $event_id ) {
	$currency_symbol = '$';
	if ( '' !== rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_CURRENCY ) ) {
		$currency_symbol = rsvp_pro_get_currency_symbol( rsvp_pro_get_event_option( $event_id, RSVP_PRO_OPTION_CURRENCY ) );
	}

	return $currency_symbol;
}

/**
 * Retrieves the symbol releated to a currency code.
 *
 * @param  string $currency_code The currency code we want the symbol for.
 * @return string                The currency symbol, if nothing is found then $ will be returned.
 */
function rsvp_pro_get_currency_symbol( $currency_code ) {
	$symbol = '$';

	foreach ( rsvp_pro_get_currencies() as $currency ) {
		if ( strtoupper( $currency['code'] ) === strToUpper( $currency_code ) ) {
			$symbol = $currency['symbol'];
			break;
		}
	}

	return $symbol;
}
