<?php
/**
 * WP Courseware Install.
 *
 * @package WPCW
 * @subpackage Core
 * @since 4.3.0
 */
namespace WPCW\Core;

use WPCW\Models\Course;
use WPCW_queue_dripfeed;

// Exit if accessed directly
defined( 'ABSPATH' ) || exit;

/**
 * Class Install
 *
 * @since 4.3.0
 */
final class Install {

	/**
	 * @var Process The upgrader process.
	 * @since 4.4.0
	 */
	protected $upgrader;

	/**
	 * @var array Upgrade callbacks.
	 * @since 4.4.0
	 */
	protected $upgrades = array(
		'4.3.0' => array(
			'wpcw_upgrade_430_ecommerce',
		),
		'4.4.0' => array(
			'wpcw_upgrade_440_courses',
		),
	);

	/**
	 * @var bool Flush rewrite rules?
	 * @since 4.4.0
	 */
	protected $flush_rules = false;

	/**
	 * Load Activate Class.
	 *
	 * @since 4.3.0
	 */
	public function load() {
		register_activation_hook( WPCW_FILE, array( $this, 'install' ) );
		add_action( 'wpcw_init', array( $this, 'upgrade' ), 0 );
	}

	/**
	 * Install Plugin.
	 *
	 * @since 4.3.0
	 */
	public function install() {
		// Register Settings.
		wpcw()->settings->register_settings();

		// Remove flush rules flag.
		wpcw_remove_flush_rewrite_rules_flag();

		// Create upload directory
		wpcw_create_upload_directory();

		// Clean up tags
		WPCW_tag_cleanup();

		// Setup or clear the scheduler for the notifications timers. If the setting is 'never'
		// then clear the scheduler. If it's anything else, then add it.
		$dripfeedSetting = WPCW_TidySettings_getSettingSingle( WPCW_DATABASE_SETTINGS_KEY, 'cron_time_dripfeed' );
		WPCW_queue_dripfeed::installNotificationHook_dripfeed( ( ! empty( $dripfeedSetting ) ) ? $dripfeedSetting : 'twicedaily' );

		// Create Roles & Capabilities
		$roles = new Roles();
		$roles->add_roles();
		$roles->add_caps();

		// Install Pages.
		if ( $this->can_install_ecommerce() ) {
			$this->install_pages();
		}

		// Send Initial Checkin
		$this->maybe_send_initial_checkin();

		/**
		 * Action: Flush Rewrite Rules.
		 *
		 * @since 4.4.0
		 */
		do_action( 'wpcw_flush_rewrite_rules' );
	}

	/**
	 * Upgrade Plugin.
	 *
	 * @since 4.3.0
	 */
	public function upgrade() {
		// DB Version.
		$installed_db_version = get_option( 'wpcw_db_version', null );
		$current_db_version   = WPCW_DB_VERSION;

		// Version.
		$installed_version = get_option( 'wpcw_plugin_version', null );
		$current_version   = WPCW_VERSION;

		// Initial Vars.
		$action = 'wpcw_upgrader';
		$prefix = 'wpcw_' . get_current_blog_id();
		$queued = false;

		// Upgrader.
		$this->upgrader = new Process( $action, $prefix );

		// Versions do not match, upgrade.
		if ( $current_version != $installed_version ) {
			// Not null so needs upgrade.
			if ( ! is_null( $installed_version ) ) {
				// Check if we are not already running this routine.
				if ( 'yes' === get_transient( 'wpcw_upgrading' ) ) {
					return;
				}

				$this->log( sprintf( 'Upgrading from version %s to %s.', $installed_version, $current_version ) );

				set_transient( 'wpcw_upgrading', 'yes', MINUTE_IN_SECONDS * 10 );
				wpcw_maybe_define_constant( 'WPCW_UPGRADING', true );

				// Check for upgrade callbacks.
				foreach ( $this->upgrades as $version => $upgrade_callbacks ) {
					if ( version_compare( $installed_version, $version, '<' ) ) {
						foreach ( $upgrade_callbacks as $upgrade_callback ) {
							$this->log( sprintf( 'Queuing %s - %s', $version, $upgrade_callback ) );
							$this->upgrader->push_to_queue( array( $this, $upgrade_callback ) );
							$queued = true;
						}
					}
				}

				// Dispatch Queue.
				if ( $queued ) {
					$this->upgrader->save()->dispatch();
				}

				// Delete Transient.
				delete_transient( 'wpcw_upgrading' );

				// Update Versions.
				update_option( 'wpcw_plugin_version', WPCW_VERSION );
				update_option( 'wpcw_db_version', WPCW_DB_VERSION );

				/**
				 * Action: Upgraded.
				 *
				 * @since 4.4.0
				 */
				do_action( 'wpcw_upgraded' );
			} else {
				// Update Versions.
				update_option( 'wpcw_plugin_version', WPCW_VERSION );
				update_option( 'wpcw_db_version', WPCW_DB_VERSION );
			}

			// Remove Flush Rules Flag.
			wpcw_remove_flush_rewrite_rules_flag();

			/**
			 * Action: Flush Rewrite Rules.
			 *
			 * @since 4.4.0
			 */
			do_action( 'wpcw_flush_rewrite_rules' );
		}

		// Create Uploads Directory.
		wpcw_create_upload_directory();
	}

	/**
	 * Can Install E-Commerce?
	 *
	 * @since 4.3.0
	 *
	 * @return bool True if the pages can be installed.
	 */
	public function can_install_ecommerce() {
		$can_install = true;

		if ( $can_install ) {
			$ecommerce_plugins = apply_filters( 'wpcw_install_ecommerce_plugins', array(
				'easy-digital-downloads/easy-digital-downloads.php',
				'woocommerce/woocommerce.php',
				'learnpress/learnpress.php',
				'memberpress/memberpress.php',
				'paid-memberships-pro/paid-memberships-pro.php',
				'easy-digital-downloads-addon-for-wp-courseware/wp-courseware-edd.php',
				'magic-member-addon-for-wp-courseware/wp-courseware-magic-members.php',
				'membermouse-addon-for-wp-courseware/wp-courseware-member-mouse.php',
				'memberpress-addon-for-wp-courseware/wp-courseware-memberpress.php',
				'membersonic-addon-for-wp-courseware/wp-courseware-membersonic.php',
				'om-addon-for-wp-courseware/wp-courseware-optimizemember.php',
				'paid-memberships-pro-for-wp-courseware/wp-courseware-pmpro.php',
				'premise-addon-for-wp-courseware/wp-courseware-premise.php',
				's2member-addon-for-wp-courseware/wp-courseware-s2-member.php',
				'wishlist-member-addon-for-wp-courseware/wp-courseware-wishlist-member.php',
				'woo-commerce-addon-for-wp-courseware/wp-courseware-woo-commerce.php',
			) );

			if ( ! function_exists( 'is_plugin_active' ) ) {
				include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
			}

			foreach ( $ecommerce_plugins as $plugin ) {
				if ( is_plugin_active( $plugin ) ) {
					$can_install = false;
					break;
				}
			}
		}

		return $can_install;
	}

	/**
	 * Install Initial Pages.
	 *
	 * @since 4.4.0
	 */
	public function install_pages() {
		$pages = array( 'courses_page', 'checkout_page', 'order_received_page', 'order_failed_page', 'terms_page', 'account_page' );

		foreach ( $pages as $page ) {
			$page_id = wpcw_get_setting( $page );

			if ( wpcw_page_exists( $page_id ) ) {
				continue;
			}

			switch ( $page ) {
				case 'courses_page' :
					$page_id = wpcw()->courses->create_courses_page();
					break;
				case 'checkout_page' :
					$page_id = wpcw()->checkout->create_checkout_page();
					break;
				case 'order_received_page' :
					$page_id = wpcw()->checkout->create_checkout_order_received_page();
					break;
				case 'order_failed_page' :
					$page_id = wpcw()->checkout->create_checkout_order_failed_page();
					break;
				case 'terms_page' :
					$page_id = wpcw()->checkout->create_checkout_terms_page();
					break;
				case 'account_page' :
					$page_id = wpcw()->students->create_students_account_page();
					break;
			}

			if ( 0 !== absint( $page_id ) ) {
				wpcw_update_setting( $page, absint( $page_id ) );
			}
		}

		add_action( 'shutdown', array( $this, 'maybe_flush_rewrite_rules' ) );
	}

	/**
	 * Upgrade 4.3.0 - Ecommerce.
	 *
	 * @since 4.3.0
	 */
	public function wpcw_upgrade_430_ecommerce() {
		if ( $this->can_install_ecommerce() ) {
			$this->install_pages();
			$this->maybe_flush_rewrite_rules();
		}
	}

	/**
	 * Upgrade 4.4.0 - Courses.
	 *
	 * This will perform the upgrade of courses.
	 *
	 * @since 4.4.0
	 */
	public function wpcw_upgrade_440_courses() {
		// Upgrade Courses.
		wpcw()->courses->maybe_upgrade_courses();

		// Roles
		$roles = new Roles();

		// Remove
		$roles->remove_roles();
		$roles->remove_caps();

		// Add
		$roles->add_roles();
		$roles->add_caps();

		// Maybe Send Inintial Checkin.
		$this->maybe_send_initial_checkin();
	}

	/**
	 * Maybe Flush Rewrite Rules.
	 *
	 * @since 4.4.0
	 */
	public function maybe_flush_rewrite_rules() {
		flush_rewrite_rules();
	}

	/**
	 * Send Initial Checkin.
	 *
	 * @since 4.4.0
	 */
	public function maybe_send_initial_checkin() {
		wp_schedule_single_event( time() + 60, 'wpcw_tracker_send_initial_checkin' );
	}

	/**
	 * Log Message.
	 *
	 * @since 4.4.0
	 *
	 * @param string $message The log message.
	 */
	public function log( $message = '' ) {
		if ( empty( $message ) || ! defined( 'WP_DEBUG' ) || true !== WP_DEBUG ) {
			return;
		}

		$log_entry = "\n" . '====Start ' . get_called_class() . ' Log====' . "\n" . $message . "\n" . '====End ' . get_called_class() . ' Log====' . "\n";

		wpcw_log( $log_entry );
		wpcw_file_log( array( 'message' => $log_entry ) );
	}
}