<?php
/**
 * Class to handle everything on the front
 */

use Simple_Giveaways\GA_Sharing;
use Simple_Giveaways\SG_Giveaway;
use Simple_Giveaways\SG_Subscriber;

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

/**
 * Class GiveASAP_Front
 */
class GiveASAP_Front {

	/**
	 * GiveAWAY Steps
	 *
	 * @var integer
	 */
	private $step = 1;

	/**
	 * Post variable
	 *
	 * @var null
	 */
	private $post = null;

	/**
	 * Posted Data from Form
	 *
	 * @var null
	 */
	public $posted_data = null;

	/**
	 * Errors
	 *
	 * @var null
	 */
	public $errors = null;

	/**
	 * Notices to Display if available
	 *
	 * @var null
	 */
	public $notices = null;

	/**
	 * Successes to Display if available
	 *
	 * @var null
	 */
	public $successes = array();

	/**
	 * Unique ID
	 *
	 * @var integer
	 */
	public $uniqid = 0;

	/**
	 * Referent ID - to view your social links
	 *
	 * @var integer
	 */
	public $refID = 0;

	/**
	 * Share ID - from sharing links
	 *
	 * @var integer
	 */
	public $shareID = 0;

	/**
	 * The permalink
	 *
	 * @var string
	 */
	private $permalink = '';

	/**
	 * Sharing methods
	 *
	 * @var null
	 */
	private $sharing = null;

	/**
	 * Current Entries
	 *
	 * @var integer
	 */
	public $current_entries = 0;

	/**
	 * Registered User
	 *
	 * @var null
	 */
	public $user = null;

	/**
	 * User who shared
	 *
	 * @var null
	 */
	public $sharer = null;

	/**
	 * GiveASAP Settings
	 *
	 * @var array
	 */
	public $giveasap_settings = array();

	/**
	 * Giveaway object.
	 *
	 * @var null|SG_Giveaway
	 */
	private $giveaway = null;

	/**
	 * From Page.
	 *
	 * @var null
	 */
	public $registered_from_page = null;

	/**
	 * Redirect Link
	 *
	 * @var string
	 */
	public $redirect_link = '';

	/**
	 * Constructing the Front
	 *
	 * @param int|WP_Post $post Post Object.
	 * @param bool        $process Process the registration and other things..
	 */
	public function __construct( $post, $process = true ) {
		$this->post      = $post;
		$this->giveaway  = giveasap_get_giveaway( $post );
		$this->permalink = get_permalink( $post->ID );
		$this->errors    = new \WP_Error();

		// Force preview step if in iframe preview mode. The builder POSTs the
		// preview request, so read from $_REQUEST. Gated by is_admin() — the
		// preview renders through admin.php; on public pages these parameters
		// must not fake a subscriber view.
		if ( is_admin() && isset( $_REQUEST['giveasap_iframe_preview'] ) && isset( $_REQUEST['preview_step'] ) && in_array( absint( $_REQUEST['preview_step'] ), [ 1, 2 ] ) ) {
			$this->set_step( absint( $_REQUEST['preview_step'] ) );
			$this->set_uniqid( 'preview' );
			$this->refID = 'preview';
            $this->user =  json_decode(json_encode([
                    'id' => 1,
                    'entries' => 100,
                    'email' => 'example@example.com',
                    'ref_id' => 'preview'
            ]));
			$process = false;
		}

		if ( $process ) {
			if ( $this->giveaway->has_custom_registration_flow() ) {
				$this->giveaway->custom_registration_flow( $this );
			} else {
				$this->process_request_link();
				$this->check_cookie();
				$this->check_logged_user();
				$this->get_ref();
				$this->maybe_activate();
				$this->get_share();
				$this->creating_steps();
				$this->edit_fields();

				if ( isset( $_GET['sg_error'] ) ) {
					$this->add_error( 'sg-error', \Simple_Giveaways\Helpers::unslash_and_clean( $_GET['sg_error'] ) );
				}
			}
		}

		if ( 2 === $this->step ) {
			$display       = $this->giveaway->get_display_settings();
			$this->sharing = new GA_Sharing( $this->get_share_link(), $this->post->post_title, $display );
		}

	}

	/**
	 * Set the Share URL
	 *
	 * @param string $url URL from where we share.
	 */
	public function set_share_url( $url ) {
		if ( null === $this->sharing ) {
			return;
		}

		$this->sharing->set_sharing_url( $this->get_share_link( false, $url ) );
	}

	/**
	 * Set the from page.
	 *
	 * @param string $url URL.
	 */
	public function set_from_page( $url ) {
		$this->registered_from_page = $url;
	}

	/**
	 * Get the from page value.
	 *
	 * @return string|null
	 */
	public function get_from_page() {
		return $this->registered_from_page;
	}

	/**
	 * Activate the User.
	 *
	 * @since 2.11.0
	 */
	private function maybe_activate() {
		if ( null !== $this->user && isset( $_GET['activate'] ) && 1 === absint( $_GET['activate'] ) ) {
			// We have a user and we have the activation trigger.
			$activate = giveasap_activate_user( $this->user->id );
			if ( $activate ) {
				$this->user->status = 'active';
			}
		}
	}

	/**
	 * Sending a Referral Link on Request
	 *
	 * @since  2.6.2
	 *
	 * @return void
	 */
	public function process_request_link() {

		if ( isset( $_POST['giveasap_request_link'] ) ) {
			$this->posted_data = $this->unslash_and_clean( $_POST );

			if ( ! isset( $this->posted_data['request_email'] )
				|| '' === $this->posted_data['request_email'] ) {
				$this->add_error( 'email', __( 'Email is empty', 'giveasap' ) );
				return;
			}

			$this->notices[] = __( 'Subscribed links sent if the email is subscribed.', 'giveasap' );

			giveasap_send_request_link_email( $this->posted_data['request_email'], $this->post->ID );

		}

	}

	/**
	 * Get share link
	 *
	 * @param boolean        $encode_url If true, it will encode the url.
	 * @param string|boolean $link If link is not passed, it will default to giveaway link.
	 *
	 * @return false|mixed|string Link with the sharing tag
	 */
	public function get_share_link( $encode_url = false, $link = false ) {

		$share_id = 0;

		if ( $this->user ) {
			$share_id = $this->user->id;
		}

		if ( ! $share_id ) {

			if ( $link ) {
				return $link;
			}

			return '';
		}

		if ( ! $link ) {
			$link = $this->permalink;
		}

		if ( false === strpos( $link, '?' ) ) {
			$link .= '?';
		} else {
			$link .= '&';
		}

		$link .= 'share=' . $share_id;

		$link = remove_query_arg( 'ref', $link );

		if ( $encode_url ) {
			$link = urlencode( $link );
		}

		return $link;
	}

	/**
	 * Create unique ID
	 */
	public function create_uniqid() {
		$this->uniqid = md5( uniqid() );

		if ( giveasap_ref_id_exists( $this->uniqid, $this->post->ID ) ) {
			$this->create_uniqid();
		}
	}

	/**
	 * Unslash and clean the data.
	 *
	 * @param mixed $var Data to sanitize.
	 *
	 * @return array|string
	 */
	public function unslash_and_clean( $var ) {
		return \Simple_Giveaways\Helpers::unslash_and_clean( $var );
	}

	/**
	 * Get referent ID if supplied. This will create the step 2 with sharing links
	 *
	 * @return void
	 */
	public function get_ref() {
		if ( 1 === $this->step && isset( $_GET['ref'] ) && $this->unslash_and_clean( $_GET['ref'] ) ) {
			$this->refID = $this->unslash_and_clean( $_GET['ref'] );
			$this->user  = giveasap_get_user( $this->refID, $this->post->ID );

			if ( null !== $this->user ) {
				$this->set_uniqid( $this->refID );

				// Make sure we are using the ID.
				$this->create_cookie();

				$this->set_step( 2 );
			}
		}
	}

	/**
	 * Check for a Logged In User. If it exists, try to get it by email
	 *
	 * @return void
	 *
	 * @since  2.5.0
	 */
	public function check_logged_user() {
		if ( 1 === $this->step && null === $this->user ) {

			if ( is_user_logged_in() ) {

				$current_user = wp_get_current_user();

				if ( $current_user ) {
					$this->user = giveasap_get_user_by_email( $current_user->get( 'user_email' ), $this->post->ID );

					if ( null !== $this->user ) {
						$this->refID = $this->user->ref_id;
						$this->set_uniqid( $this->user->ref_id );
						$this->create_cookie();
						$this->set_step( 2 );
					}
				}
			}
		}
	}

	/**
	 * Check cookie, if exists, it will create the step 2 page
	 *
	 * @return void
	 */
	public function check_cookie() {
		if ( 1 === $this->step && isset( $_COOKIE ) && isset( $_COOKIE[ 'giveasap_' . absint( $this->post->ID ) ] ) ) {
			$this->refID = $this->unslash_and_clean( $_COOKIE[ 'giveasap_' . absint( $this->post->ID ) ] );

			$this->user = giveasap_get_user( $this->refID, $this->post->ID );

			if ( null !== $this->user ) {
				$this->set_uniqid( $this->refID );
				$this->set_step( 2 );
			}
		}
	}

	/**
	 * Get the share ID if supplied. This will set an input to count up the entry
	 *
	 * @return void
	 */
	public function get_share() {

		// If the giveaway does not collect entries, we don't need this.
		if ( ! $this->giveaway->is_collecting_entries() ) {
			return;
		}

		// We don't need that if we are already on step 2.
		if ( 2 === $this->step ) {
			return;
		}

		if ( isset( $_GET['share'] ) && $this->unslash_and_clean( $_GET['share'] ) ) {
			$this->shareID = $this->unslash_and_clean( $_GET['share'] );
		}

		if ( isset( $_POST['user_share'] ) && $this->unslash_and_clean( $_POST['user_share'] ) ) {
			$this->shareID = $this->unslash_and_clean( $_POST['user_share'] );
		}

		if ( is_numeric( $this->shareID ) ) {
			$this->sharer = giveasap_get_user_by_id( $this->shareID, $this->post->ID );
		} else {

			$this->sharer = giveasap_get_user( $this->shareID, $this->post->ID );
		}

		if ( null !== $this->sharer ) {
			// Let's make sure we are using the ID instead of ref_id.
			$this->shareID = $this->sharer->id;
		} else {
			$this->shareID = 0;
		}
	}

	/**
	 * Gets the uniqe ID
	 *
	 * @return int
	 */
	public function get_uniqid() {
		return $this->uniqid;
	}

	/**
	 * Set the uniqe ID
	 *
	 * @param string $uniqid
	 */
	public function set_uniqid( $uniqid ) {
		$this->uniqid = $uniqid;
	}

	/**
	 * Show Current Entries of a Referent ID
	 *
	 * @return void
	 */
	public function current_entries() {
		if ( null !== $this->user ) {
			echo esc_html( $this->user->entries );
		}
	}

	/**
	 * Show Current Entries of a Referent ID
	 *
	 * @return integer
	 */
	public function get_current_entries() {
		if ( null !== $this->user ) {
			return $this->user->entries;
		}

		return 0;
	}

	/**
	 * Get the form link with the ref ID set
	 *
	 * @return string Form Action link
	 */
	public function get_form_link() {

		$giveaway = $this->get_giveaway();

		if ( $giveaway ) {
			$link = $giveaway->get_main_page_link();
		} else {
			$link = $this->permalink;
		}

		return $link;
	}

	/**
	 * Set the step
	 *
	 * @param number $step
	 */
	public function set_step( $step ) {
		$this->step = $step;
	}

	/**
	 * Get Step
	 *
	 * @return number
	 */
	public function get_step() {
		return apply_filters( 'sg_front_get_step', $this->step, $this );
	}

	/**
	 * Return the giveaway
	 *
	 * @return null|\Simple_Giveaways\SG_Giveaway
	 */
	public function get_giveaway() {
		return $this->giveaway;
	}

	/**
	 * Return the giveaway
	 *
	 * @param \Simple_Giveaways\SG_Giveaway
	 */
	public function set_giveaway( $giveaway ) {
		if ( is_a( $giveaway, 'SG_Giveaway' ) ) {
			$this->giveaway = $giveaway;
		}
	}

	/**
	 * Return the subscriber or false if we don't have one.
	 *
	 * @return bool|SG_Subscriber
	 */
	public function get_subscriber() {
		if ( null === $this->user ) {
			return false;
		}

		return giveasap_get_subscriber( $this->user, $this->get_giveaway_id() );
	}

	/**
	 * Check if user exists
	 *
	 * @return boolean
	 */
	public function user_exists() {
		return $this->giveaway->subscriber_exists( $this->posted_data['sg_form']['user_email'] );
	}

	/**
	 * Add error
	 *
	 * @param string $code
	 * @param string $message
	 */
	public function add_error( $code, $message ) {
		$this->errors->add( $code, $message );
	}

	/**
	 * Show the error from code
	 *
	 * @param string $code error code.
	 */
	public function show_errors( $code = '' ) {
		$errors = $this->errors->get_error_messages( $code );
		if ( ! empty( $errors ) ) {
			foreach ( $errors as $error ) {
				echo '<p class="giveasap_error">' . esc_html( $error ) . '</p>';
			}
			if ( $code ) {
				// Don't show them more than once.
				$this->errors->remove( $code );
			} else {
				foreach ( $this->errors->get_error_codes() as $code ) {
					$this->errors->remove( $code );
				}
			}
		}
	}

	/**
	 * Show Notices
	 */
	public function show_notices() {
		$notices = $this->notices;
		if ( $notices ) {
			foreach ( $notices as $notice ) {
				echo '<p class="giveasap_notice">' . wp_kses_post( $notice ) . '</p>';
			}
		}
	}

	/**
	 * Show Success Notices
	 */
	public function show_successes() {
		$notices = $this->successes;
		if ( $notices ) {
			foreach ( $notices as $notice ) {
				echo '<p class="giveasap_success">' . wp_kses_post( $notice ) . '</p>';
			}
		}
	}

	/**
	 * Register a user
	 *
	 * @return boolean|WP_Error
	 */
	public function register_user() {

		if ( ! $this->giveaway->is_open_to_subscribe() ) {
			return new \WP_Error( 'not-open', $this->giveaway->get_not_open_reason() );
		}

		if ( isset( $this->giveasap_settings['disallow_blocked_subscribers'] ) && '1' === $this->giveasap_settings['disallow_blocked_subscribers'] ) {
			if ( giveasap_is_email_blocked( $this->posted_data['sg_form']['user_email'] ) ) {
				return new \WP_Error( 'email-blocked', __( 'Your email is blocked.', 'giveasap' ) );
			}
		}

		$registered_id = $this->giveaway->add_subscriber( $this->posted_data['sg_form']['user_email'] );

		if ( is_wp_error( $registered_id ) ) {
			return $registered_id;
		}

		if ( $registered_id ) {
			$this->user = $this->giveaway->get_subscriber( $registered_id );
			$this->set_uniqid( $this->user->ref_id );
			$this->set_share_entry();
			$this->create_cookie();
			if ( is_user_logged_in() ) {
				giveasap_add_meta( $registered_id, 'user_id', get_current_user_id() );
			}
			if ( giveasap_is_ip_enabled() ) {
				giveasap_add_meta( $registered_id, '_ip', giveasap_get_ip_address() );
			}
			return $registered_id;
		}

		return new \WP_Error( 'no-register', __( 'Something went wrong. Please try again or contact the administrator.', 'giveasap' ) );
	}

	/**
	 * Create Cookie for a registered user
	 *
	 * @return void
	 */
	public function create_cookie() {

		if ( headers_sent() ) {
			return;
		}

        $cookie_length = apply_filters( 'giveasap_cookie_length', time() + ( 30 * DAY_IN_SECONDS ) );

		setcookie( 'giveasap_' . $this->post->ID, $this->user->ref_id, $cookie_length, COOKIEPATH, COOKIE_DOMAIN );
	}

	/**
	 * Process Google Captcha
	 *
	 * @return void
	 */
	public function process_captcha() {
		/* If Google Site Key exists */
		if ( $this->giveasap_settings['google_site_key'] ) {

			if ( ! isset( $this->posted_data['g-recaptcha-response'] ) ) {
				$this->add_error( 'google', __( 'Google Captcha failed', 'giveasap' ) );
				$this->set_step( 1 );
				return;
			}

			if ( '' === $this->posted_data['g-recaptcha-response'] ) {
				$this->add_error( 'google', __( 'Google Captcha failed', 'giveasap' ) );
				$this->set_step( 1 );
				return;
			}

			$google_post = wp_remote_post(
				'https://www.google.com/recaptcha/api/siteverify',
				array(
					'body' => array(
						'secret'   => $this->giveasap_settings['google_secret_key'],
						'response' => $this->posted_data['g-recaptcha-response'],
					),
				)
			);

			if ( is_wp_error( $google_post ) ) {
				$this->add_error( 'google', $google_post->get_error_message() );
				$this->set_step( 1 );
				return;
			}

			$google_json = json_decode( wp_remote_retrieve_body( $google_post ), true );

			if ( ! $google_json['success'] ) {

				$google_error_strings = array(
					'missing-input-secret'   => __( 'The secret parameter is missing.', 'giveasap' ),
					'invalid-input-secret'   => __( 'The secret parameter is invalid or malformed.', 'giveasap' ),
					'missing-input-response' => __( 'The response parameter is missing.', 'giveasap' ),
					'invalid-input-response' => __( 'The response parameter is invalid or malformed.', 'giveasap' ),
				);

				$google_errors = isset( $google_json['error-codes'] ) ? $google_json['error-codes'] : '';
				if ( is_array( $google_errors ) ) {
					foreach ( $google_errors as $error_code ) {
						$this->add_error( 'google', $google_error_strings[ $error_code ] );
					}
				} else {
					$error = isset( $google_error_strings[ $google_errors ] ) ? $google_error_strings[ $google_errors ] : __( 'Something went wrong with Captcha. Try again.', 'giveasap' );
					$this->add_error( 'google', $error );
				}

				$this->set_step( 1 );
				return;
			}
		}
	}

	/**
	 * Validate Form Fields
	 *
	 * @return bool
	 */
	public function validate_form_fields() {
		$ret = true;

		if ( apply_filters( 'sg_skip_form_fields_validation', false ) ) {
			return true;
		}

		$form_fields = isset( $this->posted_data['sg_form'] ) ? $this->posted_data['sg_form'] : false;

		if ( ! $form_fields ) {
			$this->add_error( 'no-fields', __( 'No posted form fields', 'giveasap' ) );
		}

		$registered_fields = giveasap_get_form_fields( $this->get_giveaway_id() );
		foreach ( $registered_fields as $field_name => $field ) {
			$required = isset( $field['required'] ) ? (bool) $field['required'] : false;

			$value = isset( $form_fields[ $field_name ] ) ? $form_fields[ $field_name ] : '';

			if ( $value && ( 'select' === $field['type'] || 'radio' === $field['type'] ) ) {
				$options = isset( $field['options'] ) ? $field['options'] : array();
				// If no option, this field will revert to being a text type.
				if ( $options ) {
					if ( ! in_array( $value, $options, true ) ) {
						// translators: %s - posted value.
						$this->add_error( 'no-' . $field_name, sprintf( __( '%s is not correct.', 'giveasap' ), $value ) );
						$ret = false;
					}
				}
			}

            if ( 'image' === $field['type'] ) {
                $value = ! empty( wp_unslash( $_FILES['sg_form_' . $field_name ] ) );

                if ( $value ) {
                    $image_check = \Simple_Giveaways\Helpers::check_uploaded_file( wp_unslash( $_FILES['sg_form_' . $field_name ] ), array( 'jpg', 'jpeg', 'png' ) );

                    if ( is_wp_error( $image_check ) ) {
                        $this->add_error( 'not-valid-' . $field_name, $image_check->get_error_message() );
                        $ret = false;
                    }
                }
            }

			if ( $required && ! $value ) {
				// translators: %s - field label.
				$this->add_error( 'no-' . $field_name, sprintf( __( 'Field %s is required.', 'giveasap' ), $field['label'] ) );
				$ret = false;
			}
		}

		return $ret;
	}

	/**
	 * Validating posted data.
	 *
	 * @since 2.16.0
	 *
	 * @param boolean $editing If we are validating while editing or not.
	 */
	public function validate_posted_data( $editing = false ) {
		if ( ! $this->posted_data ) {
			return false;
		}

		if ( is_user_logged_in() ) {
			$user                                       = wp_get_current_user();
			$this->posted_data['sg_form']['user_email'] = $user->user_email;
		}

		$ret = $this->validate_form_fields();

		if ( giveasap_is_gdpr_active() && ( ! isset( $this->posted_data['giveasap_consent'] ) || '1' !== $this->posted_data['giveasap_consent'] ) ) {
			$this->add_error( 'consent', __( 'You need to agree to our terms.', 'giveasap' ) );
			$ret = false;
		}

		return apply_filters( 'giveasap_giveaway_validate_posted_data', $ret, $editing, $this );
	}

	/**
	 * Create the steps and register if needed
	 *
	 * @return void
	 */
	public function creating_steps( $redirect = true ) {
		$this->posted_data = $this->unslash_and_clean( $_POST );
		if ( $this->posted_data && isset( $this->posted_data['giveasap_submit'] ) ) {

			if ( ! isset( $_POST['sg_giveaway_type'] ) ) {
				$_POST['sg_giveaway_type']             = $this->get_giveaway()->get_type();
				$this->posted_data['sg_giveaway_type'] = $this->get_giveaway()->get_type();
			}
			$this->giveasap_settings = giveasap_get_settings();

			if ( ! $this->validate_posted_data() ) {
				$this->set_step( 1 );
				return;
			}

			if ( $this->user_exists() ) {

				if ( ! giveasap_is_email_login_enabled() ) {
					$this->add_error( 'email', __( 'Email is already subscribed', 'giveasap' ) );
					$this->set_step( 1 );
					/**
					 * Hook so people can still be signed in if needed.
					 *
					 * @since 2.23.0
					 */
					do_action( 'sg_user_exists', $this );

					return;
				} else {
					// We have a user already with that email. Let's just login it.
					$subscriber = giveasap_get_user_by_email( $this->posted_data['sg_form']['user_email'], $this->get_giveaway_id() );
					$entry_link = add_query_arg( 'ref', $subscriber->ref_id, $this->permalink );
					$page       = giveasap_get_meta( $subscriber->id, '_from_page', true );

					if ( $page ) {
						$entry_link = add_query_arg( 'ref', $subscriber->ref_id, $page );
					}

					if ( $redirect && $entry_link ) {
						// Let's redirect it.
						wp_redirect( $entry_link, 301 );
						exit();
					} else {
						$this->successes[] = __( 'Subscribed.', 'giveasap' );
					}
				}
			}

			/**
			 * We don't need to process captcha if the user is logged in
			 */
			if ( ! is_user_logged_in() && apply_filters( 'sg_process_captcha', true ) ) {
				$this->process_captcha();
			}

			/**
			 * @since 2.13.0
			 */
			do_action( 'sg_process_registration', $this );

			$errors = $this->errors->get_error_codes();

			if ( ! $errors ) {

				$registered = $this->register_user();

				if ( ! is_wp_error( $registered ) ) {

					$send_default_email = apply_filters( 'giveasap_send_registered_email', true, $this->get_giveaway(), $this->user );

					$entry_link = add_query_arg( 'ref', $this->user->ref_id, $this->permalink );

					// If we don't show a page, let's not use it.
					if ( ! $this->get_giveaway()->showing_subscriber_page() ) {
						$entry_link = '';
					}

					if ( isset( $_POST['sg_from_page'] ) ) {
						// Adding ref id to redirect url so caching system can ignore it.
						$entry_link = add_query_arg( 'ref', $this->user->ref_id, $this->unslash_and_clean( $_POST['sg_from_page'] ) );
						giveasap_update_meta( $registered, '_from_page', $this->unslash_and_clean( $_POST['sg_from_page'] ) );
					}

					if ( $send_default_email ) {
						giveasap_send_registered_email( $this->user->id );
					}

					/**
					 * Notify the administrator on each subscribe
					 *
					 * @since 2.7.0
					 */
					if ( isset( $this->giveasap_settings['notify_on_subscribe'] ) && '1' === $this->giveasap_settings['notify_on_subscribe'] ) {
						giveasap_send_notify_on_subscribe_email( $this->user->id, $this->posted_data );
					}

					$general = $this->get_giveaway()->get_general_settings();

					// Setting it to redirect the user.
					if ( $redirect && isset( $general['sg_redirect'] ) && $general['sg_redirect'] ) {
						$entry_link = add_query_arg( 'ref', $this->user->ref_id, $general['sg_redirect'] );
					}

					$this->redirect_link = apply_filters( 'sg_giveaway_redirect_entry_link', $entry_link, $this );

					if ( $redirect && $this->redirect_link ) {
						// Let's redirect it.
						wp_redirect( $this->redirect_link, 301 );
						exit();
					} else {
						$this->successes[] = __( 'Subscribed.', 'giveasap' );
					}
				} else {
					$this->add_error( $registered->get_error_code(), $registered->get_error_message() );
				}
			}
		}

	}

	/**
	 * Create the steps and register if needed
	 *
	 * @return void
	 */
	public function edit_fields() {
		$this->posted_data = $this->unslash_and_clean( $_POST );
		if ( $this->posted_data && isset( $this->posted_data['giveasap_edit'] ) ) {

			if ( ! isset( $this->posted_data['sg_giveaway_subscriber'] ) ) {
				$this->add_error( 'no-subscriber', __( 'No Subscriber data.', 'giveasap' ) );
			}

			if ( ! isset( $this->posted_data['sg_giveaway_id'] ) ) {
				$this->add_error( 'no-subscriber', __( 'No Giveaway data.', 'giveasap' ) );
			}

			if ( ! isset( $this->posted_data['sg_form_edit_nonce'] ) ) {
				$this->add_error( 'no-nonce', __( 'Security data missing.', 'giveasap' ) );
			}

			if ( ! wp_verify_nonce( $this->posted_data['sg_form_edit_nonce'], 'sg_form_edit_' . $this->posted_data['sg_giveaway_subscriber'] ) ) {
				$this->add_error( 'no-nonce', __( 'No Hacking please.', 'giveasap' ) );
			}

			$subscriber = giveasap_get_subscriber( $this->posted_data['sg_giveaway_subscriber'], $this->posted_data['sg_giveaway_id'] );
			// Email can't be changed.
			$this->posted_data['sg_form']['user_email'] = $subscriber->get_email();
			// We have already given consent in case of editing.
			$this->posted_data['giveasap_consent'] = '1';

			if ( ! $this->validate_posted_data( true ) ) {
				return;
			}

			/**
			 * @since 2.13.0
			 */
			do_action( 'sg_process_edit_form', $this );

			$errors = $this->errors->get_error_codes();

			if ( ! $errors ) {
				$subscriber  = giveasap_get_subscriber( $this->posted_data['sg_giveaway_subscriber'], $this->posted_data['sg_giveaway_id'] );
				$form_fields = isset( $this->posted_data['sg_form'] ) ? $this->posted_data['sg_form'] : false;
				foreach ( $form_fields as $field_name => $field_value ) {
					if ( 'user_email' === $field_name ) {
						continue;
					}

					$subscriber->update_meta( '_' . $field_name, $field_value );
				}

				$this->successes[] = __( 'Fields updated.', 'giveasap' );

			}
		}

	}

	/**
	 * Set the entry for the shared one
	 *
	 * @return void
	 */
	public function set_share_entry() {
		if ( null !== $this->user ) {
			if ( isset( $this->posted_data['user_share'] ) && $this->posted_data['user_share'] ) {
				$this->shareID = $this->posted_data['user_share'];

				if ( is_numeric( $this->shareID ) ) {
					$this->sharer = giveasap_get_user_by_id( $this->shareID, $this->post->ID );
				} else {
					$this->sharer = giveasap_get_user( $this->shareID, $this->post->ID );
				}
			}

			// Be sure that the registered user and sharer are not the same
			if ( null !== $this->sharer && ( $this->sharer->id !== $this->user->id ) ) {
				giveasap_set_referrer( $this->user->id, $this->sharer->id );

				$entries_to_give = apply_filters( 'giveasap_entry_value', 1, $this->post->ID );

				// Is user active?
				if ( 'active' === $this->user->status ) {
					$entries = (int) $this->sharer->entries;

					$entries += $entries_to_give;

					giveasap_update_user_entry( $this->sharer->id, $entries );
					do_action( 'sg_referrer_awarded_points', $this->sharer->id, $entries_to_give, $this->user->id, $this->user->post_id );
				} else {
					giveasap_update_meta( $this->user->id, '_entries_to_give', $entries_to_give );
				}
			}
		}
	}

	/**
	 * Rendering all the sharing methods
	 *
	 * @return void
	 */
	public function render_sharing_methods() {
		$this->sharing->set_giveaway( $this->giveaway );
		$this->sharing->render();
	}

	/**
	 * Returning the Giveaway ID
	 *
	 * @since  2.5.0
	 * @return integer Post ID or 0
	 */
	public function get_giveaway_id() {

		if ( $this->post ) {
			return $this->post->ID;
		}

		return 0;
	}

	/**
	 * Hook to add the head meta.
	 */
	public function add_wp_header() {
		add_action( 'wp_head', array( $this, 'add_head_meta' ) );
	}

	/**
	 * Add the head meta.
	 */
	public function add_head_meta() {
		$giveaway = $this->get_giveaway();
		$display  = $giveaway->get_display_settings();

		$twitterImage = false;
		if ( isset( $display['twitter_image'] ) ) {
			$twitterImage = giveasap_get_image_url( $display['twitter_image'] );
		}

		$twitterAccount = '@wpgiveaways';
		if ( isset( $display['twitter_account'] ) ) {
			$twitterAccount = $display['twitter_account'];
		}

		$facebookImage = false;
		if ( isset( $display['facebook_image'] ) ) {
			$facebookImage = giveasap_get_image_url( $display['facebook_image'] );
		}

		$description = get_the_excerpt( $this->giveaway->get_post() );
		$description = wp_strip_all_tags( $description );
		$title       = $this->giveaway->get_post()->post_title;

		?>
		<!-- Twitter Card data -->
		<meta name="twitter:card" content="summary_large_image">
		<meta name="twitter:site" content="<?php echo esc_attr( $twitterAccount ); ?>">
		<meta name="twitter:title" content="<?php echo esc_attr( $title ); ?>">

		<?php if ( $description ) { ?>
			<meta name="twitter:description" content="<?php echo esc_attr( $description ); ?>">
		<?php } ?>

		<meta name="twitter:creator" content="<?php echo esc_attr( $twitterAccount ); ?>">

		<?php if ( $twitterImage ) { ?>

			<!-- Twitter summary card with large image must be at least 280x150px -->
			<meta name="twitter:image:src" content="<?php echo esc_attr( $twitterImage ); ?>">

		<?php } ?>

		<!-- Open Graph data -->
		<meta property="og:title" content="<?php echo esc_attr( $title ); ?>" />
		<meta property="og:type" content="article" />
		<meta property="og:url" content="<?php echo esc_url( get_permalink( $this->giveaway->get_post() ) ); ?>" />
		<?php if ( $facebookImage ) { ?>
			<meta property="og:image" content="<?php echo esc_attr( $facebookImage ); ?>" />
		<?php } ?>
		<?php if ( $description ) { ?>
			<meta property="og:description" content="<?php echo esc_attr( $description ); ?>" />
		<?php } ?>
		<meta property="og:site_name" content="" />
		<?php
	}

	/**
	 * Get the required scripts for the Giveaway.
	 *
	 * @return string[]
	 */
	public function required_scripts() {
		$locale = get_locale();

		return array(
			'sg-js',
			'sg-countdown',
			'sg-jquery',
			'sg-captcha',
			'sg-locale-' . $locale,
			'sg-shortcode',
		);
	}

	/**
	 * Get the required styles for the Giveaway.
	 *
	 * @return string[]
	 */
	public function required_styles() {
		return array(
			'sg-style',
			'sg-shortcode',
		);
	}

	/**
	 * Dequeue Scripts that are not for Single Giveaway page.
	 * This is used when we do not use the page layout option for faster performance.
	 */
	public function dequeue_for_single_page() {
		$wp_scripts       = wp_scripts();
		$required_scripts = $this->required_scripts();
		if ( $wp_scripts->queue ) {
			foreach ( $wp_scripts->queue as $handle ) {
				if ( ! in_array( $handle, $required_scripts, true ) ) {
					wp_dequeue_script( $handle );
				}
			}
		}

		$wp_styles       = wp_styles();
		$required_styles = $this->required_styles();
		if ( $wp_styles->queue ) {
			foreach ( $wp_styles->queue as $handle ) {
				if ( ! in_array( $handle, $required_styles, true ) ) {
					wp_dequeue_style( $handle );
				}
			}
		}
	}

	/**
	 * Enqueue
	 */
	public function enqueue() {
		$version  = gasap()->version();
		$settings = giveasap_get_settings();
		wp_enqueue_style( 'sg-style', $this->giveaway->get_style_href(), array(), $version );

		$style = '';

		if ( isset( $settings['head_styles'] ) && '' !== $settings['head_styles'] ) {
			$style .= wp_unslash( $settings['head_styles'] );
		}

		$url = false;

		$display = $this->giveaway->get_display_settings();

		if ( isset( $display['background_image'] ) && absint( $display['background_image'] ) > 0 ) {
			$url = giveasap_get_image_url( $display['background_image'] );
		}

		if ( $url ) {
			$style .= 'body{';
			$style .= 'background: url("' . $url . '") no-repeat center center;';
			$style .= 'background-size:cover;background-attachment:fixed;';
			$style .= '}';
		}

		if ( isset( $display['background_color'] ) && $display['background_color'] ) {
			$style .= ' body{ background-color: ' . $display['background_color'] . '; }';
		}

		if ( $style ) {
			wp_add_inline_style( 'sg-style', $style );
		}

		if ( 1 === $this->get_step() && isset( $settings['google_site_key'] ) && $settings['google_site_key'] ) {
			wp_enqueue_script( 'sg-captcha', 'https://www.google.com/recaptcha/api.js', array(), $version, false );
		}

		wp_enqueue_script( 'sg-jquery', GASAP_URI . '/assets/js/jquery.plugin.min.js', array( 'jquery' ), $version, true );
		wp_enqueue_script( 'sg-countdown', GASAP_URI . '/assets/js/jquery.countdown.min.js', array( 'jquery' ), $version, true );

		$locale = get_locale();

		if ( 'en_US' !== $locale && 'en_EN' !== $locale ) {
			if ( file_exists( GASAP_ROOT . '/assets/js/l10n/' . $locale . '.js' ) ) {
				wp_enqueue_script( 'sg-locale-' . $locale, GASAP_URI . '/assets/js/l10n/' . $locale . '.js', '', $version, true );
			} elseif ( isset( $settings['countdown_lang_url'] ) && $settings['countdown_lang_url'] ) {
				wp_enqueue_script( 'sg-locale-' . $locale, $settings['countdown_lang_url'], '', $version, true );
			}
		}
		if ( ! wp_script_is( 'sg-js' ) ) {
			wp_enqueue_script( 'sg-js', GASAP_URI . '/assets/dist/js/giveasap.js', '', $version, true );
			wp_localize_script( 'sg-js', 'sg', gasap()->get_localized_array() );
		}
		$script = '';

		if ( isset( $settings['footer_scripts'] ) ) {
			$script .= wp_unslash( $settings['footer_scripts'] );
		}

        $script_settings = $this->get_giveaway()->get_scripts_settings();

        if ( ! empty( $script_settings['scripts'] ) ) {
            $script .= wp_unslash( $script_settings['scripts'] );
        }

        if ( ! empty( $script_settings['visitor_scripts'] ) && $this->get_step() === 1 ) {
            $script .= wp_unslash( $script_settings['visitor_scripts'] );
        }

        if ( ! empty( $script_settings['subscriber_scripts'] ) && $this->get_step() === 2 ) {
            $script .= wp_unslash( $script_settings['subscriber_scripts'] );
        }

		if ( $script ) {
			wp_add_inline_script( 'sg-js', $script );
		}
	}
}
