<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

class AAL_Settings {
	private $hook;
	public $slug = 'activity-log-settings';
	protected $options;

	public function __construct() {
		add_action( 'init', array( &$this, 'init' ) );
		add_action( 'admin_menu', array( &$this, 'action_admin_menu' ), 30 );
		add_action( 'admin_init', array( &$this, 'register_settings' ) );
		add_action( 'admin_notices', array( &$this, 'admin_notices' ) );
		add_action( 'admin_footer', array( &$this, 'admin_footer' ) );
		add_filter( 'plugin_action_links_' . ACTIVITY_LOG_BASE, array( &$this, 'plugin_action_links' ) );

		add_action( 'wp_ajax_aal_reset_items', array( &$this, 'ajax_aal_reset_items' ) );
		add_action( 'wp_ajax_aal_get_properties', array( &$this, 'ajax_aal_get_properties' ) );
	}

	public function init() {
		$this->options = $this->get_options();
	}

	public function plugin_action_links( $links ) {
		$settings_link = sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php?page=activity-log-page' ), __( 'Activity Log', 'aryo-activity-log' ) );
		array_unshift( $links, $settings_link );

		$settings_link = sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php?page=activity-log-settings' ), __( 'Settings', 'aryo-activity-log' ) );
		array_unshift( $links, $settings_link );

		return $links;
	}

	/**
	 * Register the settings page
	 *
	 * @since 1.0
	 */
	public function action_admin_menu() {
		$this->hook = add_submenu_page(
			'activity-log-page',
			__( 'Activity Log Settings', 'aryo-activity-log' ), 	// <title> tag
			__( 'Settings', 'aryo-activity-log' ), 			// menu label
			'manage_options', 								// required cap to view this page
			$this->slug, 			// page slug
			array( &$this, 'display_settings_page' )			// callback
		);

		// register scripts & styles, specific for the settings page
		add_action( "admin_print_scripts-{$this->hook}", array( &$this, 'scripts_n_styles' ) );
		// this callback will initialize the settings for AAL
		// add_action( "load-$this->hook", array( $this, 'register_settings' ) );
	}

	/**
	 * Register scripts & styles
	 *
	 * @since 1.0
	 */
	public function scripts_n_styles() {
		wp_enqueue_script( 'aal-settings', plugins_url( 'assets/js/settings.js', ACTIVITY_LOG__FILE__ ), array( 'jquery' ) );
		wp_enqueue_style( 'aal-settings', plugins_url( 'assets/css/settings.css', ACTIVITY_LOG__FILE__ ) );
	}

	public function register_settings() {
		// If no options exist, create them.
		if ( ! get_option( $this->slug ) ) {
			update_option( $this->slug, apply_filters( 'aal_default_options', array(
				'logs_lifespan' => '30',
				'logs_failed_login' => 'yes',
				'logs_email' => 'yes',
			) ) );
		}

		register_setting( 'aal-options', $this->slug, array( $this, 'validate_options' ) );
		$section = $this->get_setup_section();

		switch ( $section ) {
			case 'general':
				// First, we register a section. This is necessary since all future options must belong to a
				add_settings_section(
					'general_settings_section',			// ID used to identify this section and with which to register options
					__( 'Display Options', 'aryo-activity-log' ),	// Title to be displayed on the administration page
					array( 'AAL_Settings_Fields', 'general_settings_section_header' ),	// Callback used to render the description of the section
					$this->slug		// Page on which to add this section of options
				);

				add_settings_field(
					'logs_lifespan',
					__( 'Keep logs for', 'aryo-activity-log' ),
					array( 'AAL_Settings_Fields', 'number_field' ),
					$this->slug,
					'general_settings_section',
					array(
						'id'      => 'logs_lifespan',
						'page'    => $this->slug,
						'classes' => array( 'small-text' ),
						'type'    => 'number',
						'sub_desc'    => __( 'days.', 'aryo-activity-log' ),
						'desc'    => __( 'Maximum number of days to keep activity log. Leave blank to keep activity log forever (not recommended).', 'aryo-activity-log' ),
					)
				);

				add_settings_field(
					'logs_failed_login',
					__( 'Keep Failed Login Logs', 'aryo-activity-log' ),
					array( 'AAL_Settings_Fields', 'select_field' ),
					$this->slug,
					'general_settings_section',
					array(
						'id'      => 'logs_failed_login',
						'page'    => $this->slug,
						'type'    => 'select',
						'options' => array(
							'yes' => __( 'Keep', 'aryo-activity-log' ),
							'no' => __( "Don't Keep (Not recommended)", 'aryo-activity-log' ),
						),
					)
				);

				add_settings_field(
					'logs_email',
					__( 'Keep Email Logs', 'aryo-activity-log' ),
					array( 'AAL_Settings_Fields', 'select_field' ),
					$this->slug,
					'general_settings_section',
					array(
						'id'      => 'logs_email',
						'page'    => $this->slug,
						'type'    => 'select',
						'options' => array(
							'yes' => __( 'Keep', 'aryo-activity-log' ),
							'no' => __( "Don't Keep", 'aryo-activity-log' ),
						),
					)
				);

				add_settings_field(
					'log_visitor_ip_source',
					__( 'Visitor IP Detected', 'aryo-activity-log' ),
					array( 'AAL_Settings_Fields', 'select_field' ),
					$this->slug,
					'general_settings_section',
					array(
						'id'      => 'log_visitor_ip_source',
						'page'    => $this->slug,
						'type'    => 'select',
						'options' => array(
							'REMOTE_ADDR' => 'REMOTE_ADDR',
							'HTTP_CF_CONNECTING_IP' => 'HTTP_CF_CONNECTING_IP',
							'HTTP_TRUE_CLIENT_IP' => 'HTTP_TRUE_CLIENT_IP',
							'HTTP_CLIENT_IP' => 'HTTP_CLIENT_IP',
							'HTTP_X_FORWARDED_FOR' => 'HTTP_X_FORWARDED_FOR',
							'HTTP_X_FORWARDED' => 'HTTP_X_FORWARDED',
							'HTTP_X_CLUSTER_CLIENT_IP' => 'HTTP_X_CLUSTER_CLIENT_IP',
							'HTTP_FORWARDED_FOR' => 'HTTP_FORWARDED_FOR',
							'HTTP_FORWARDED' => 'HTTP_FORWARDED',
                            'no-collect-ip' => __( 'Do not collect IP', 'aryo-activity-log' ),
						),
						'desc' => __( 'Select the source of the visitor IP address. For example, if you are using Cloudflare, select <code>HTTP_CF_CONNECTING_IP</code>.', 'aryo-activity-log' )
                                . '<br />'
                                . __( '<strong>Please note:</strong> if you choose "Do not collect IP", the IP column will be hidden in the log.', 'aryo-activity-log' ),
					)
				);

				if ( apply_filters( 'aal_allow_option_erase_logs', true ) ) {
					add_settings_field(
						'raw_delete_log_activities',
						__( 'Delete Log Activities', 'aryo-activity-log' ),
						array( 'AAL_Settings_Fields', 'raw_html' ),
						$this->slug,
						'general_settings_section',
						array(
							'html' => sprintf( __( '<a href="%s" id="%s">Reset Database</a>', 'aryo-activity-log' ), add_query_arg( array(
								'action' => 'aal_reset_items',
								'_nonce' => wp_create_nonce( 'aal_reset_items' ),
							), admin_url( 'admin-ajax.php' ) ), 'aal-delete-log-activities' ),
							'desc' => __( 'Warning: Clicking this will delete all activities from the database.', 'aryo-activity-log' ),
						)
					);
				}
				break;

			case 'notifications':
				// Email Notifications Settings
				add_settings_section(
					'email_notifications', // ID used to identify this section and with which to register options
					__( 'Notifications', 'aryo-activity-log' ),	// Title to be displayed on the administration page
					array( 'AAL_Settings_Fields', 'email_notifications_section_header' ),	// Callback used to render the description of the section
					$this->slug		// Page on which to add this section of options
				);

				add_settings_field(
					'notification_rules',
					__( 'Notification Events', 'aryo-activity-log' ),
					array( 'AAL_Settings_Fields', 'email_notification_buffer_field' ),
					$this->slug,
					'email_notifications',
					array(
						'id'      => 'notification_rules',
						'page'    => $this->slug,
						'desc'    => __( 'Maximum number of days to keep activity log. Leave blank to keep activity log forever (not recommended).', 'aryo-activity-log' ),
					)
				);

				$notification_handlers = AAL_Main::instance()->notifications->get_available_handlers();
				$enabled_notification_handlers = AAL_Main::instance()->settings->get_option( 'notification_handlers' );

				// Loop through custom notification handlers
				foreach ( $notification_handlers as $handler_id => $handler_obj  ) {
					if ( ! is_object( $handler_obj ) )
						continue;

					add_settings_section(
						"notification_$handler_id",
						$handler_obj->name,
						array( $handler_obj, '_settings_section_callback' ),
						$this->slug
					);

					add_settings_field(
						"notification_handler_{$handler_id}_enabled",
						__( 'Enable?', 'aryo-activity-log' ),
						array( $handler_obj, '_settings_enabled_field_callback' ),
						$this->slug,
						"notification_$handler_id",
						array(
							'id'      => 'notification_transport',
							'page'    => $this->slug,
							'name' => "{$this->slug}[notification_handlers][{$handler_id}]",
							'value' => isset( $enabled_notification_handlers[ $handler_id ] ) && ( 1 == $enabled_notification_handlers[ $handler_id ] ),
						)
					);

					$handler_obj->settings_fields();
				}
				break;
		}
	}

	/**
	 * Returns the current section within AAL's setting pages
	 *
	 * @return string
	 */
	public function get_setup_section() {
		if ( isset( $_REQUEST['aal_section'] ) )
			return strtolower( $_REQUEST['aal_section'] );

		return 'general';
	}

	/**
	 * Prints section tabs within the settings area
	 */
	private function menu_print_tabs() {
		$current_section = $this->get_setup_section();
		$sections = array(
			'general'       => __( 'General', 'aryo-activity-log' ),
		);

		$enabled_notification_handlers = AAL_Main::instance()->settings->get_option( 'notification_handlers' );

		// Hide notifications tab if not used before..
		if ( ! empty( $enabled_notification_handlers ) ) {
			$sections['notifications'] = __( 'Notifications', 'aryo-activity-log' );
		}

		$sections = apply_filters( 'aal_setup_sections', $sections );

		if ( 1 >= count( $sections ) ) {
			return;
		}

		foreach ( $sections as $section_key => $section_caption ) {
			$active = $current_section === $section_key ? 'nav-tab-active' : '';
			$url = add_query_arg( 'aal_section', $section_key );
			echo '<a class="nav-tab ' . $active . '" href="' . esc_url( $url ) . '">' . esc_html( $section_caption ) . '</a>';
		}
	}

	public function validate_options( $input ) {
		$options = $this->options; // CTX,L1504

		// @todo some data validation/sanitization should go here
		$output = apply_filters( 'aal_validate_options', $input, $options );

		// merge with current settings
		$output = array_merge( $options, $output );

		return $output;
	}

	public function display_settings_page() {
		?>
		<!-- Create a header in the default WordPress 'wrap' container -->
		<div class="wrap">

			<h1 class="aal-page-title"><?php _e( 'Activity Log Settings', 'aryo-activity-log' ); ?></h1>
			<?php settings_errors(); ?>
			<h2 class="nav-tab-wrapper"><?php $this->menu_print_tabs(); ?></h2>

			<form method="post" action="options.php">
				<?php
				settings_fields( 'aal-options' );
				do_settings_sections( $this->slug );
				submit_button();
				?>
			</form>

		</div><!-- /.wrap -->
		<?php
	}

	public function admin_notices() {
		switch ( filter_input( INPUT_GET, 'message' ) ) {
			case 'data_erased':
				printf( '<div class="updated"><p>%s</p></div>', __( 'All activities have been successfully deleted.', 'aryo-activity-log' ) );
				break;
		}
	}

	public function admin_footer() {
		// TODO: move to a separate file.
		?>
		<script type="text/javascript">
			jQuery( document ).ready( function( $ ) {
				$( '#aal-delete-log-activities' ).on( 'click', function( e ) {
					if ( ! confirm( '<?php echo __( 'Attention: We are going to DELETE ALL ACTIVITIES from the database. Are you sure you want to do that?', 'aryo-activity-log' ); ?>' ) ) {
						e.preventDefault();
					}
				} );
			} );
		</script>
		<?php
	}

	public function ajax_aal_reset_items() {
		if ( ! check_ajax_referer( 'aal_reset_items', '_nonce', false ) || ! current_user_can( 'manage_options' ) ) {
			wp_die( __( 'You do not have sufficient permissions to access this page.', 'aryo-activity-log' ) );
		}

		AAL_Main::instance()->api->erase_all_items();

		wp_redirect( add_query_arg( array(
				'page' => 'activity-log-settings',
				'message' => 'data_erased',
		), admin_url( 'admin.php' ) ) );
		die();
	}

	public function ajax_aal_get_properties() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error();
		}

		$action_category = isset( $_REQUEST['action_category'] ) ? $_REQUEST['action_category'] : false;

		$options = AAL_Main::instance()->notifications->get_settings_dropdown_values( $action_category );

		if ( ! empty( $options ) ) {
			wp_send_json_success( $options );
		}

		wp_send_json_error();
	}

	public function get_option( $key = '' ) {
		$settings = $this->get_options();
		return ! empty( $settings[ $key ] ) ? $settings[ $key ] : false;
	}

	/**
	 * Returns all options
	 *
	 * @since 2.0.7
	 * @return array
	 */
	public function get_options() {
		// Allow other plugins to get AAL's options.
		if ( isset( $this->options ) && is_array( $this->options ) && ! empty( $this->options ) )
			return $this->options;

		return apply_filters( 'aal_options', get_option( $this->slug, array() ) );
	}

	public function slug() {
		return $this->slug;
	}
}

// TODO: Need rewrite this class to useful tool.
final class AAL_Settings_Fields {

	public static function general_settings_section_header() {
		?>
		<p><?php _e( 'These are some basic settings for Activity Log.', 'aryo-activity-log' ); ?></p>
		<?php
	}

	public static function email_notifications_section_header() {
		?>
		<p><?php _e( 'Serve yourself with custom-tailored notifications. First, define your conditions. Then, choose how the notifications will be sent.', 'aryo-activity-log' ); ?></p>
		<?php
	}

	public static function raw_html( $args ) {
		if ( empty( $args['html'] ) )
			return;

		echo wp_kses_post( $args['html'] );
		if ( ! empty( $args['desc'] ) ) : ?>
			<p class="description"><?php echo wp_kses_post( $args['desc'] ); ?></p>
		<?php endif;
	}

	public static function text_field( $args ) {
		self::_set_name_and_value( $args );
		extract( $args, EXTR_SKIP );

		$args = wp_parse_args( $args, array(
			'classes' => array(),
		) );
		if ( empty( $args['id'] ) || empty( $args['page'] ) )
			return;

		?>
		<input type="text" id="<?php echo esc_attr( $args['id'] ); ?>" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value ); ?>" class="<?php echo implode( ' ', $args['classes'] ); ?>" />
		<?php if ( ! empty( $desc ) ) : ?>
		<p class="description"><?php echo wp_kses_post( $desc ); ?></p>
		<?php endif;
	}

	public static function textarea_field( $args ) {
		self::_set_name_and_value( $args );
		extract( $args, EXTR_SKIP );

		$args = wp_parse_args( $args, array(
			'classes' => array(),
			'rows'    => 5,
			'cols'    => 50,
		) );

		if ( empty( $args['id'] ) || empty( $args['page'] ) )
			return;

		?>
		<textarea id="<?php echo esc_attr( $args['id'] ); ?>" name="<?php echo esc_attr( $name ); ?>" class="<?php echo implode( ' ', $args['classes'] ); ?>" rows="<?php echo absint( $args['rows'] ); ?>" cols="<?php echo absint( $args['cols'] ); ?>"><?php echo esc_textarea( $value ); ?></textarea>

		<?php if ( ! empty( $desc ) ) : ?>
			<p class="description"><?php echo wp_kses_post( $desc ); ?></p>
		<?php endif;
	}

	public static function number_field( $args ) {
		self::_set_name_and_value( $args );
		extract( $args, EXTR_SKIP );

		$args = wp_parse_args( $args, array(
			'classes' => array(),
			'min' => '1',
			'step' => '1',
			'desc' => '',
		) );
		if ( empty( $args['id'] ) || empty( $args['page'] ) )
			return;

		?>
		<input type="number" id="<?php echo esc_attr( $args['id'] ); ?>" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value ); ?>" class="<?php echo implode( ' ', $args['classes'] ); ?>" min="<?php echo esc_attr( $args['min'] ); ?>" step="<?php echo esc_attr( $args['step'] ); ?>" />
		<?php if ( ! empty( $args['sub_desc'] ) ) echo wp_kses_post( $args['sub_desc'] ); ?>
		<?php if ( ! empty( $args['desc'] ) ) : ?>
			<p class="description"><?php echo wp_kses_post( $args['desc'] ); ?></p>
		<?php endif;
	}

	public static function select_field( $args ) {
		self::_set_name_and_value( $args );
		extract( $args, EXTR_SKIP );

		if ( empty( $options ) || empty( $id ) || empty( $page ) )
			return;

		?>
		<select id="<?php echo esc_attr( $id ); ?>" name="<?php printf( '%s[%s]', esc_attr( $page ), esc_attr( $id ) ); ?>">
			<?php foreach ( $options as $name => $label ) : ?>
			<option value="<?php echo esc_attr( $name ); ?>" <?php selected( $name, (string) $value ); ?>>
				<?php echo esc_html( $label ); ?>
			</option>
			<?php endforeach; ?>
		</select>
		<?php if ( ! empty( $desc ) ) : ?>
		<p class="description"><?php echo wp_kses_post( $desc ); ?></p>
		<?php endif; ?>
		<?php
	}

	public static function yesno_field( $args ) {
		self::_set_name_and_value( $args );
		extract( $args, EXTR_SKIP );

		?>
		<label class="tix-yes-no description"><input type="radio" name="<?php echo esc_attr( $name ); ?>" value="1" <?php checked( $value, true ); ?>> <?php _e( 'Yes', 'aryo-activity-log' ); ?></label>
		<label class="tix-yes-no description"><input type="radio" name="<?php echo esc_attr( $name ); ?>" value="0" <?php checked( $value, false ); ?>> <?php _e( 'No', 'aryo-activity-log' ); ?></label>

		<?php if ( isset( $args['description'] ) ) : ?>
		<p class="description"><?php echo wp_kses_post( $args['description'] ); ?></p>
		<?php endif; ?>
		<?php
	}

	public static function email_notification_buffer_field( $args ) {
		$args = wp_parse_args( $args, array(
			'classes' => array(),
		) );
		if ( empty( $args['id'] ) || empty( $args['page'] ) )
			return;

		// available action categories
		$keys = array(
			'user' 			=> __( 'User', 'aryo-activity-log' ),
			'action-type' 	=> __( 'Action Type', 'aryo-activity-log' ),
			'action-value'  => __( 'Action Performed', 'aryo-activity-log' ),
		);
		// available condition types
		$conditions = array(
			'equals' => __( 'equals to', 'aryo-activity-log' ),
			'not_equals' => __( 'not equals to', 'aryo-activity-log' ),
		);

		$common_name = sprintf( '%s[%s]', esc_attr( $args['page'] ), esc_attr( $args['id'] ) );

		// get all rows
		$rows = AAL_Main::instance()->settings->get_option( $args['id'] );
		// if empty, reset to one element with the key of 1
		$rows = empty( $rows ) ? array( array( 'key' => 1 ) ) : $rows;
		?>
		<p class="description"><?php _e( 'A notification will be sent upon a successful match with the following conditions:', 'aryo-activity-log' ); ?></p>
		<div class="aal-notifier-settings">
			<ul>
			<?php foreach ( $rows as $rid => $row ) :
				$row_key 		= $row['key'];
				$row_condition 	= isset( $row['condition'] ) ? $row['condition'] : '';
				$row_value 		= isset( $row['value'] ) ? $row['value'] : '';
				?>
				<li data-id="<?php echo esc_attr( $rid ); ?>">
					<select name="<?php echo esc_attr( $common_name ); ?>[<?php echo esc_attr( $rid ); ?>][key]" class="aal-category">
						<?php foreach ( $keys as $k => $v ) : ?>
						<option value="<?php echo esc_attr( $k ); ?>" <?php selected( $row_key, $k ); ?>><?php echo esc_attr( $v ); ?></option>
						<?php endforeach; ?>
					</select>
					<select name="<?php echo esc_attr( $common_name ); ?>[<?php echo esc_attr( $rid ); ?>][condition]" class="aal-condition">
						<?php foreach ( $conditions as $k => $v ) : ?>
						<option value="<?php echo esc_attr( $k ); ?>" <?php selected( $row_condition, $k ); ?>><?php echo esc_html( $v ); ?></option>
						<?php endforeach; ?>
					</select>
					<?php $value_options = AAL_Main::instance()->notifications->get_settings_dropdown_values( $row_key ); ?>
					<select name="<?php echo esc_attr( $common_name ); ?>[<?php echo esc_attr( $rid ); ?>][value]" class="aal-value">
						<?php foreach ( $value_options as $option_key => $option_value ) : ?>
						<option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( $option_key, $row_value ); ?>><?php echo esc_html( $option_value ); ?></option>
						<?php endforeach; ?>
					</select>
					<a href="#" class="aal-new-rule button"><small>+</small> <?php _e( 'and', 'aryo-activity-log' ); ?></a>
					<a href="#" class="aal-delete-rule button">&times;</a>
				</li>
			<?php endforeach; ?>
			</ul>
		</div>
		<?php
	}

	private static function _set_name_and_value( &$args ) {
		if ( ! isset( $args['name'] ) ) {
			$args['name'] = sprintf( '%s[%s]', esc_attr( $args['page'] ), esc_attr( $args['id'] ) );
		}

		if ( ! isset( $args['value'] ) ) {
			$args['value'] = AAL_Main::instance()->settings->get_option( $args['id'] );
		}
	}
}
