<?php
/**
 * Simple Giveaway Class
 */

namespace Simple_Giveaways;

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

/**
 * Class SG_Giveaway
 */
abstract class SG_Giveaway {

	/**
	 * Giveaway ID.
	 *
	 * @var int
	 */
	protected $id = 0;

	/**
	 * Type of the Giveaway.
	 *
	 * @var string
	 */
	protected $type = '';

	/**
	 * @var null|\WP_Post
	 */
	protected $post = null;

	/**
	 * @var null
	 */
	protected $schedule = null;

	/**
	 * All Settings.
	 *
	 * @var array
	 */
	protected $settings = array();

	/**
	 * Supports
	 *
	 * @var array
	 */
	protected $supports = array();

	/**
	 * SG_Giveaway constructor.
	 *
	 * @param int|\WP_Post $giveaway
	 */
	public function __construct( $giveaway ) {
		$this->set_post( $giveaway );
	}

	/**
	 * Return the Statuses that declare that a Giveaway has ended.
	 *
	 * @since 2.17.2
	 *
	 * @return array
	 */
	public function get_end_statuses() {
		return apply_filters(
			'sg_giveaway_end_statuses',
			array(
				'giveasap_ended',
				'giveasap_winners',
				'giveasap_notified',
			)
		);
	}

	/**
	 * Giveaway Supports
	 *
	 * @param $feature
	 *
	 * @return boolean
	 */
	public function supports( $feature ) {
		$features = apply_filters( 'sg_giveaway_supports', $this->supports, $this->get_type(), $feature, $this );
		if ( in_array( $feature, $features, true ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Check if the giveaway has ended.
	 *
	 * @return bool
	 */
	public function has_ended() {

		if ( in_array( $this->post->post_status, $this->get_end_statuses(), true ) ) {
			return true;
		}

		$datetime = new \DateTime();

		$now = $datetime->getTimestamp();

		$giveaway_id = $this->get_id();

		if ( ! $giveaway_id ) {
			return false;
		}

		$end_time = giveasap_get_end_time( $giveaway_id );

		if ( ! $end_time ) {
			return false;
		}

		$datetime->setTimestamp( $end_time );

		$end = $datetime->getTimestamp();

		if ( $now > $end ) {
			return true;
		}

		return false;
	}

	/**
	 * Check if the giveaway has started.
	 *
	 * @since 2.16.0
	 *
	 * @return bool
	 */
	public function has_started() {

		$giveaway_id = $this->get_id();

		if ( ! $giveaway_id ) {
			return false;
		}

		$schedule   = $this->get_schedule();
		$start_time = $schedule->get_start_timestamp();
		$datetime   = new \DateTime();
		$now        = $datetime->getTimestamp();

		if ( $now >= $start_time ) {
			return true;
		}

		return false;
	}

	/**
	 * Is Giveaway showing the subscriber page or only the first form?
	 *
	 * @return boolean
	 */
	public function showing_subscriber_page() {
		return apply_filters( 'sg_giveaway_showing_subscriber_page', true, $this );
	}

	/**
	 * Is this Giveaway open for subscriptions?
	 *
	 * @return bool
	 */
	public function is_open_to_subscribe() {
		return apply_filters( 'sg_giveaway_open_to_subscribe', true, $this );
	}

	/**
	 * Return the reason for a closed giveaway.
	 *
	 * @return string
	 */
	public function get_not_open_reason() {
		return '';
	}

	/**
	 * Is this Giveaway collecting entries?
	 *
	 * @return mixed
	 */
	public function is_collecting_entries() {
		return apply_filters( 'sg_giveaway_collecting_entries', true, $this );
	}

	/**
	 * Is this Giveaway displaying entries?
	 *
	 * @return mixed
	 */
	public function is_displaying_entries() {
		return apply_filters( 'sg_giveaway_displaying_entries', $this->is_collecting_entries(), $this );
	}

	/**
	 * Check if the subscriber exists.
	 *
	 * @param $email
	 *
	 * @return bool
	 */
	public function subscriber_exists( $email ) {
		return giveasap_user_exists( $email, $this->get_id() );
	}

	/**
	 * Add Subscriber to this Giveaway
	 *
	 * @param string $email
	 *
	 * @return integer|\WP_Error Entry ID or Error
	 */
	public function add_subscriber( $email ) {

		$is_email = apply_filters( 'sg_is_valid_email', is_email( $email ), $email );

		if ( ! $is_email ) {
			return new \WP_Error( 'email-invalid', __( 'Email is not valid', 'giveasap' ) );
		}

		if ( ! giveasap_is_email_allowed( $email ) ) {
			return new \WP_Error( 'email-not-allowed', __( 'Email domain is not allowed.', 'giveasap' ) );

		}

		if ( $this->subscriber_exists( $email ) ) {
			return new \WP_Error( 'user-exists', __( 'There is already a subscriber with that email', 'giveasap' ) );
		}

		// Create a random ref ID.
		$ref_id = md5( time() . $email );

		$initial_entry_point = apply_filters( 'sg_initial_subscriber_entry_point', 1, $this );

		return giveasap_register_user( $this->get_id(), $email, $initial_entry_point, $ref_id );
	}

	/**
	 * @param mixed  $value Can be a string or a number. Mostly a string.
	 * @param string $by    This can be set to 'id' or 'email'.
	 */
	public function get_subscriber( $value, $by = 'id' ) {
		switch ( $by ) {
			case 'id':
				return giveasap_get_user_by_id( $value, $this->get_id() );
				break;
			case 'email':
				return giveasap_get_user_by_email( $value, $this->get_id() );
				break;
			case 'ref_id':
				return giveasap_get_user( $value, $this->get_id() );
				break;
		}

		return apply_filters( 'sg_giveaway_get_subscriber', false );
	}

	/**
	 * Return the ID.
	 *
	 * @return int
	 */
	public function get_id() {
		return $this->id;
	}

	/**
	 * Return the type of the giveaway.
	 *
	 * @return string
	 */
	public function get_type() {
		return $this->type;
	}

	/**
	 * @return null|\WP_Post
	 */
	public function get_post() {
		return $this->post;
	}

	/**
	 * @return GA_Schedule|null
	 */
	public function get_schedule() {
		if ( null === $this->schedule ) {
			$this->get_settings();
			$schedule       = isset( $this->settings['giveasap_schedule'] ) ? $this->settings['giveasap_schedule'] : '';
			$this->schedule = new GA_Schedule( $schedule, $this->get_post() );
		}

		return $this->schedule;
	}

	/**
	 * Return the general settings.
	 */
	public function get_schedule_settings() {
		$settings = $this->get_settings();
		return isset( $settings['giveasap_schedule'] ) ? $settings['giveasap_schedule'] : array();
	}

	/**
	 * Return the general settings.
	 */
	public function get_general_settings() {
		$settings = $this->get_settings();
		return isset( $settings['giveasap_general'] ) ? $settings['giveasap_general'] : array();
	}

	/**
	 * Get the display settings.
	 *
	 * @return array|mixed
	 */
	public function get_display_settings() {
		$settings = $this->get_settings();
		return isset( $settings['giveasap_display'] ) ? $settings['giveasap_display'] : array();
	}

    /**
     * Get the scripts settings.
     *
     * @return array|mixed
     */
    public function get_scripts_settings() {
        $settings = $this->get_settings();
        return isset( $settings['giveasap_scripts'] ) ? $settings['giveasap_scripts'] : array();
    }

	/**
	 * Get the display settings.
	 *
	 * @return array|mixed
	 */
	public function get_prize_settings() {
		$settings = $this->get_settings();
		return isset( $settings['giveasap_prize'] ) ? $settings['giveasap_prize'] : array();
	}

	/**
	 * Get the display settings.
	 *
	 * @return array|mixed
	 */
	public function get_text_settings() {
		$settings = $this->get_settings();
		return isset( $settings['giveasap_text'] ) ? $settings['giveasap_text'] : array();
	}

	public function get_setting( $key ) {
		$settings = $this->get_settings();

		return isset( $settings[ $key ] ) ? $settings[ $key ] : array();
	}

	/**
	 * Get all settings.
	 *
	 * @param boolean $force Force the settings to be retrieved again. Introduced in 2.12.0
	 *
	 * @return array
	 */
	public function get_settings( $force = false ) {
		if ( ! $this->settings || $force ) {
			$meta_settings = apply_filters(
				'sg_giveaway_meta_settings',
				array(
					'giveasap_general',
					'giveasap_prize',
					'giveasap_schedule',
					'giveasap_display',
					'giveasap_text',
                    'giveasap_scripts',
				)
			);

			foreach ( $meta_settings as $meta_key ) {
				if ( ! isset( $this->settings[ $meta_key ] ) ) {
					$this->settings[ $meta_key ] = get_post_meta( $this->get_id(), $meta_key, true );
				}
			}
		}

		return $this->settings;
	}

	/**
	 * Get total entries in the giveaway
	 *
	 * @return number
	 */
	public function get_total_entries() {
		global $wpdb;

		$count = $wpdb->get_var( "SELECT SUM(entries) FROM $wpdb->giveasap_entries" );

		if ( ! $count ) {
			return 0;
		}

		return absint( $count );
	}

	/**
	 * Get template name.
	 *
	 * @return string
	 */
	public function get_template_name() {
		$template_name = 'template1';

		return apply_filters( 'giveasap_display_template', $template_name, $this->get_display_settings() );
	}

	/**
	 * Get the template path.
	 *
	 * @return string
	 */
	public function get_template_path() {
		$template_path = 'templates/';

		return apply_filters( 'giveasap_display_template_path', $template_path );
	}

	/**
	 * Get the template file to include.
	 *
	 * @return string
	 */
	public function get_template_file() {

		$template_path = $this->get_template_path();
		$template_name = $this->get_template_name();

		return $template_path . $template_name . '.php';
	}

	/**
	 * Get the link to the style of the current template.
	 *
	 * @return string
	 */
	public function get_style_href() {
		return apply_filters( 'giveasap_template_style_href', GASAP_URI . '/assets/dist/css/style1.css', $this->get_display_settings() );
	}

	/**
	 * @param int|\WP_Post $post
	 *
	 * @throws \Exception
	 */
	public function set_post( $post ) {
		if ( is_numeric( $post ) ) {
			$post = get_post( $post );
		}

		if ( ! is_a( $post, 'WP_Post' ) ) {
			throw new \Exception( __( 'Post has to be an instance of WP_Post', 'giveasap' ) );
		}

		$this->post = $post;
		$this->id   = $post->ID;
	}

	/**
	 *
	 * @param \GiveASAP_Front $front
	 */
	public function get_header_message( $front ) {
		return '';
	}

	/**
	 * If this giveaway has custom registration flow
	 *
	 * @return bool
	 */
	public function has_custom_registration_flow() {
		return false;
	}

	/**
	 * @param \GiveASAP_Front $front
	 */
	public function custom_registration_flow( $front ) {

	}

	/**
	 * Get the Main Page Link
	 *
	 * @return false|mixed|string|\WP_Error
	 */
	public function get_main_page_link() {
		$general = $this->get_general_settings();

		if ( isset( $general['sg_giveaway_page'] ) && $general['sg_giveaway_page'] && false !== strpos( $general['sg_giveaway_page'], 'http' ) ) {
			return $general['sg_giveaway_page'];
		}

		return get_permalink( $this->get_post() );
	}
}
