<?php
/**
 * Settings class file.
 *
 * @package WordPress Plugin Template/Settings
 */

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

/**
 * Settings class.
 */
class Affiliate_Link_Checker_Settings {

	/**
	 * The single instance of Affiliate_Link_Checker_Settings.
	 *
	 * @var     object
	 * @access  private
	 * @since   1.0.0
	 */
	private static $_instance = null; //phpcs:ignore

	/**
	 * The main plugin object.
	 *
	 * @var     object
	 * @access  public
	 * @since   1.0.0
	 */
	public $parent = null;

	/**
	 * Prefix for plugin settings.
	 *
	 * @var     string
	 * @access  public
	 * @since   1.0.0
	 */
	public $base = '';

	/**
	 * Available settings for plugin.
	 *
	 * @var     array
	 * @access  public
	 * @since   1.0.0
	 */
	public $settings = array();

	/**
	 * Constructor function.
	 *
	 * @param object $parent Parent object.
	 */
	public function __construct( $parent ) {
		$this->parent = $parent;

		$this->base = 'alfchecker__';

		// Initialise settings.
		add_action( 'init', array( $this, 'aflc_init_settings' ), 11 );

		// Register plugin settings.
		add_action( 'admin_init', array( $this, 'alfc_register_settings' ) );

		// Add settings page to menu.
		add_action( 'admin_menu', array( $this, 'aflc_add_menu_item' ) );

		// Add settings link to plugins page.
		add_filter(
			'plugin_action_links_' . plugin_basename( $this->parent->file ),
			array(
				$this,
				'aflc_add_settings_link',
			)
		);

		// Configure placement of plugin settings page. See readme for implementation.
		add_filter( $this->base . 'menu_settings', array( $this, 'aflc_configure_settings' ) );
	}

	/**
	 * Initialise settings
	 *
	 * @return void
	 */
	public function aflc_init_settings() {
		$this->settings = $this->settings_fields();
	}

	/**
	 * Add settings page to admin menu
	 *
	 * @return void
	 */
	public function aflc_add_menu_item() {

		$args = $this->menu_settings();

		// Do nothing if wrong location key is set.
		if ( is_array( $args ) && isset( $args['location'] ) && function_exists( 'add_' . $args['location'] . '_page' ) ) {
			switch ( $args['location'] ) {
				case 'options':
				case 'submenu':
					$page = add_submenu_page( $args['parent_slug'], $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
					break;
				case 'menu':
					$page = add_menu_page( $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'], $args['icon_url'], $args['position'] );
					break;
				default:
					return;
			}
			add_action( 'admin_print_styles-' . $page, array( $this, 'settings_assets' ) );
		}
	}

	/**
	 * Prepare default settings page arguments
	 *
	 * @return mixed|void
	 */
	private function menu_settings() {
		return apply_filters(
			$this->base . 'menu_settings',
			array(
				'location'    => 'menu', // Possible settings: options, menu, submenu.
				'parent_slug' => 'options-general.php',
				'page_title'  => __( 'Aff Link Checker', 'affiliate-link-checker' ),
				'menu_title'  => __( 'Link Checker', 'affiliate-link-checker' ),
				'capability'  => 'manage_options',
				'menu_slug'   => $this->parent->_token . '_settings',
				'function'    => array( $this, 'settings_page' ),
				'icon_url'    => 'dashicons-admin-links',
				'position'    => null,
			)
		);
	}

	/**
	 * Container for settings page arguments
	 *
	 * @param array $settings Settings array.
	 *
	 * @return array
	 */
	public function aflc_configure_settings( $settings = array() ) {
		return $settings;
	}

	/**
	 * Load settings JS & CSS
	 *
	 * @return void
	 */
	public function settings_assets() {

		// We're including the farbtastic script & styles here because they're needed for the colour picker
		// If you're not including a colour picker field then you can leave these calls out as well as the farbtastic dependency for the wpt-admin-js script below.
		wp_enqueue_style( 'farbtastic' );
		wp_enqueue_script( 'farbtastic' );

		// We're including the WP media scripts here because they're needed for the image upload field.
		// If you're not including an image upload then you can leave this function call out.
		wp_enqueue_media();

		wp_register_script( $this->parent->_token . '-settings-js', $this->parent->assets_url . 'js/settings' . $this->parent->script_suffix . '.js', array( 'farbtastic', 'jquery' ), '1.0.0', true );
		wp_enqueue_script( $this->parent->_token . '-settings-js' );
	}

	/**
	 * Add settings link to plugin list table
	 *
	 * @param  array $links Existing links.
	 * @return array        Modified links.
	 */
	public function aflc_add_settings_link( $links ) {
		$settings_link = '<a href="options-general.php?page=' . $this->parent->_token . '_settings">' . __( 'Settings', 'affiliate-link-checker' ) . '</a>';
		array_push( $links, $settings_link );
		return $links;
	}

	/**
	 * Build settings fields
	 *
	 * @return array Fields to be displayed on settings page
	 */
	private function settings_fields() {

		$settings['settings'] = array(
			'title'       => __( 'Which URL should I check?', 'affiliate-link-checker' ),
			'description' => __( 'In this section you can tell me which URLs you want me to check.', 'affiliate-link-checker' ),
			'fields'      => array(
				array(
					'id'          => 'alc_method',
					'label'       => __( 'Method', 'affiliate-link-checker' ),
					'description' => __( '', 'affiliate-link-checker' ),
					'type'        => 'select',
					'options'     => array(
						'contain'    => 'URLs Containing',
						'exact'    => 'Exact URL Match',
						'list'    => 'List URL Match',
					),
					'default'     => 'contain',
				),
				array(
					'id'          => 'alc_value',
					'label'       => __( 'Value', 'affiliate-link-checker' ),
					'description' => __( '', 'affiliate-link-checker' ),
					'type'        => 'text',
					'default'     => '/ir',
					'placeholder' => __( '/go', 'affiliate-link-checker' ),
				),
				array(
					'id'          => 'alc_list',
					'label'       => __( 'List', 'affiliate-link-checker' ),
					'description' => __( '', 'affiliate-link-checker' ),
					'type'        => 'textarea',
					'default'     => '',
					'placeholder' => __( 'https://url1.com/, https://url2.com/', 'affiliate-link-checker' ),
				),
			),
		);

		$settings['notifications'] = array(
			'title'       => __( 'How should I alert you?', 'affiliate-link-checker' ),
			'description' => __( 'In this section you can setup how you want to receive the alerts about your affiliate links.', 'affiliate-link-checker' ),
			'fields'      => array(
				array(
					'id'          => 'alc_slack_hook',
					'label'       => __( 'Slack Hook', 'affiliate-link-checker' ),
					'description' => __( 'Add your custom slack hook to be notified regarding broken links.', 'affiliate-link-checker' ),
					'type'        => 'text',
					'default'     => '',
					'placeholder' => __( 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX', 'affiliate-link-checker' ),
				),
				array(
					'id'          => 'alc_email',
					'label'       => __( 'Email to Notify', 'affiliate-link-checker' ),
					'description' => __( 'We\'ll email you regarding the status of your affiliate links.', 'affiliate-link-checker' ),
					'type'        => 'text',
					'default'     => get_bloginfo('admin_email'),
					'placeholder' => get_bloginfo('admin_email'),
				),

				array(
					'id'          => 'alc_interval',
					'label'       => __( 'Frequency', 'affiliate-link-checker' ),
					'description' => __( 'How frequently do you want us to check your links?.', 'affiliate-link-checker' ),
					'type'        => 'radio',
					'options'     => array(
						'daily' => 'Daily',
						'hourly'   => 'Hourly',
					),
					'default'     => 'daily',
				),
			),
		);

		$settings = apply_filters( $this->parent->_token . '_settings_fields', $settings );

		return $settings;
	}

	/**
	 * Register plugin settings
	 *
	 * @return void
	 */
	public function alfc_register_settings() {
		if ( is_array( $this->settings ) ) {

			// Check posted/selected tab.
			$_GET   = filter_input_array(INPUT_GET, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
			$_POST  = filter_input_array(INPUT_POST, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
			
			$current_section = '';
			
			if ( isset( $_POST['tab'] ) && $_POST['tab'] ) {
				$current_section = sanitize_key($_POST['tab']);
			} else {
				if ( isset( $_GET['tab'] ) && $_GET['tab'] ) {
					$current_section = sanitize_key($_GET['tab']);
				}
			}

			foreach ( $this->settings as $section => $data ) {

				if ( $current_section && $current_section !== $section ) {
					continue;
				}

				// Add section to page.
				add_settings_section( $section, $data['title'], array( $this, 'settings_section' ), $this->parent->_token . '_settings' );

				foreach ( $data['fields'] as $field ) {

					// Validation callback for field.
					$validation = '';
					if ( isset( $field['callback'] ) ) {
						$validation = $field['callback'];
					}

					// Register field.
					$option_name = $this->base . $field['id'];
					register_setting( $this->parent->_token . '_settings', $option_name, $validation );

					// Add field to page.
					add_settings_field(
						$field['id'],
						$field['label'],
						array( $this->parent->admin, 'display_field' ),
						$this->parent->_token . '_settings',
						$section,
						array(
							'field'  => $field,
							'prefix' => $this->base,
						)
					);
				}

				if ( ! $current_section ) {
					break;
				}
			}
		}
	}

	/**
	 * Settings section.
	 *
	 * @param array $section Array of section ids.
	 * @return void
	 */
	public function settings_section( $section ) {
		?>
			<p><?php echo esc_html($this->settings[ $section['id'] ]['description']); ?></p>
		<?php
	}

	/**
	 * Load settings page content.
	 *
	 * @return void
	 */
	public function settings_page() {

		?>
			<div class="wrap" id="<?php echo esc_attr($this->parent->_token) ?>_settings">
			<h2><?php _e( 'Affiliate Link Checker Settings', 'affiliate-link-checker' ) ?></h2>
		<?php
			$tab = '';
		//phpcs:disable
		if ( isset( $_GET['tab'] ) && $_GET['tab'] ) {
			$tab .=  sanitize_key($_GET['tab']);
		}
		//phpcs:enable

		// Show page tabs.
		if ( is_array( $this->settings ) && 1 < count( $this->settings ) ) {
			?>
				<h2 class="nav-tab-wrapper">
			<?php
			$c = 0;
			foreach ( $this->settings as $section => $data ) {

				// Set tab class.
				$class = 'nav-tab';
				if ( ! isset( $_GET['tab'] ) ) { //phpcs:ignore
					if ( 0 === $c ) {
						$class .= ' nav-tab-active';
					}
				} else {
					if ( isset( $_GET['tab'] ) && $section == $_GET['tab'] ) { //phpcs:ignore
						$class .= ' nav-tab-active';
					}
				}

				// Set tab link.
				$tab_link = add_query_arg( array( 'tab' => $section ) );
				if ( isset( $_GET['settings-updated'] ) ) { //phpcs:ignore
					$tab_link = remove_query_arg( 'settings-updated', $tab_link );
				}

				?>
					<a href="<?php echo esc_attr($tab_link) ?>" class="<?php echo esc_attr( $class ) ?>"><?php echo esc_html( $data['title'] ) ?></a>
				<?php
				++$c;
			}
			?>
			</h2>
			<?php
		}
			?>
				<form method="post" action="options.php" enctype="multipart/form-data">
			<?php
				// Get settings fields.
				ob_start();
				settings_fields( $this->parent->_token . '_settings' );
				do_settings_sections( $this->parent->_token . '_settings' );
				echo ob_get_clean();
				?>
				<p class="submit">
				<input type="hidden" name="tab" value="<?php echo esc_attr( $tab ); ?>" />
				<input name="Submit" type="submit" class="button-primary" value="<?php echo esc_attr( __( 'Save Settings', 'affiliate-link-checker' ) ) ?>" />
				</p>
				</form>
				</div>

		<?php
	}

	/**
	 * Main Affiliate_Link_Checker_Settings Instance
	 *
	 * Ensures only one instance of Affiliate_Link_Checker_Settings is loaded or can be loaded.
	 *
	 * @since 1.0.0
	 * @static
	 * @see Affiliate_Link_Checker()
	 * @param object $parent Object instance.
	 * @return object Affiliate_Link_Checker_Settings instance
	 */
	public static function instance( $parent ) {
		if ( is_null( self::$_instance ) ) {
			self::$_instance = new self( $parent );
		}
		return self::$_instance;
	} // End instance()

	/**
	 * Cloning is forbidden.
	 *
	 * @since 1.0.0
	 */
	public function __clone() {
		_doing_it_wrong( __FUNCTION__, esc_html( __( 'Cloning of Affiliate_Link_Checker_API is forbidden.' ) ), esc_attr( $this->parent->_version ) );
	} // End __clone()

	/**
	 * Unserializing instances of this class is forbidden.
	 *
	 * @since 1.0.0
	 */
	public function __wakeup() {
		_doing_it_wrong( __FUNCTION__, esc_html( __( 'Unserializing instances of Affiliate_Link_Checker_API is forbidden.' ) ), esc_attr( $this->parent->_version ) );
	} // End __wakeup()

}
