<?php
/**
 * Notification Event class.
 *
 * Base Notification class extended by all notifications.
 *
 * Aims to provide a standardized way of creating and managing notifications.
 *
 * Notifications can have two types of buttons:
 * - Links: Simple links (internal or external). Can be added by just appending them to the $buttons array
 * - Actions: These provide a way of executing more complex logic (such as installing other plugins).
 *            These are added using the `add_action` function present in the class.
 *            This can be done from the `prepare` function.
 *
 *            Each action must have a label for the button and a name. The name will be used to trigger the action.
 *            A function with the name `perform_action_{action-name}` must exist in the Notification registering the action
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

abstract class SimpleStats_Notification_Event {

	/**
	 * Unique notification id
	 *
	 * @var string
	 */
	public $id;

	/**
	 * Notification title
	 *
	 * @var string
	 */
	public $title;

	/**
	 * Notification content
	 *
	 * @var string
	 */
	public $content;

	/**
	 * When the notification will repeat (e.g: 7) here `7` to repeat the notification after each 7 days, 0 for showing after installation.
	 * Only accept numeric value
	 *
	 * @var number
	 */
	public $interval = 0;

	/**
	 * When the notification will be active from, default: now
	 *
	 * @var string
	 */
	public $active_from;

	/**
	 * For how many days the notification will be active
	 *
	 * @var string
	 */
	public $active_until;

	/**
	 * Priority of this notification: 1-3
	 *
	 * @var int
	 */
	public $priority = 2;

	/**
	 * Notification icon to display with content
	 *
	 * @var string
	 */
	public $icon = 'default';

	/**
	 * Whether the notification comes from the plugin's site
	 *
	 * @var bool
	 */
	public $is_remote = false;

	/**
	 * Notification actions
	 *
	 * @var array
	 */
	public $buttons = array();

	/**
	 * @since 1.0.0
	 */
	public function __construct() {
		$this->active_from = $this->get_formatted_date( 'now' );

		if ( $this->interval > 0 ) {
			$this->active_until = $this->get_formatted_date( '+' . $this->interval . ' day' );
		} else {
			$this->active_until = $this->get_formatted_date( '+1 day' );
		}
	}

	/**
	 * Helper function for dates
	 *
	 * @param $readable_time
	 * @return false|string
	 */
	public function get_formatted_date( $readable_time ) {
		return gmdate( 'Y-m-d H:i:s', strtotime( $readable_time ) );
	}

	/**
	 * Check if notification should be displayed based on its dates range
	 *
	 * @return bool
	 */
	public function date_range_check() {
		$now = $this->get_formatted_date( 'now' );

		if ( ! empty( $this->active_from ) && $now < $this->active_from ) {
			return false;
		}

		// Ignore if expired.
		if ( ! empty( $this->active_until ) && $now > $this->active_until ) {
			return false;
		}

		return true;
	}

	/**
	 * Determine if notification should appear or not
	 * Child class can (and probably should) extend this function
	 *
	 * @return boolean
	 */
	public function should_display() {
		// We can add more check here if needed.
		return $this->date_range_check();
	}

	/**
	 * Prepare notification data
	 *
	 * @return SimpleStats_Notification_Event
	 */
	public function prepare() {
		return $this;
	}

	/**
	 * Flatten this notification into the plain array that gets persisted.
	 *
	 * Notifications are stored as arrays rather than serialized objects so the
	 * `simplestats_notifications` option never depends on a class being loaded
	 * to be readable. A serialized object unserializes to
	 * __PHP_Incomplete_Class whenever the option is read before these class
	 * files are required (WP-CLI, a REST bootstrap, another plugin walking
	 * options), and every `$item->id` read against one of those is a fatal.
	 *
	 * The field list is explicit — not get_object_vars() — because this shape is
	 * also the JSON contract the Vue notification drawer consumes, so a new
	 * internal property must not silently leak into the DB or the response.
	 *
	 * @return array
	 */
	public function to_array() {
		return array(
			'id'           => (string) $this->id,
			'title'        => (string) $this->title,
			'content'      => (string) $this->content,
			'interval'     => (int) $this->interval,
			'active_from'  => (string) $this->active_from,
			'active_until' => (string) $this->active_until,
			'priority'     => (int) $this->priority,
			'icon'         => (string) $this->icon,
			'is_remote'    => (bool) $this->is_remote,
			'buttons'      => is_array( $this->buttons ) ? $this->buttons : array(),
		);
	}
}
