<?php
/**
 * The file that defines the core plugin class
 *
 * A class definition that includes attributes and functions used across both the
 * public-facing side of the site and the admin area.
 *
 * @link    https://personalizewp.com
 * @since   1.0.0
 *
 * @package PersonalizeWP
 */

namespace PersonalizeWP;

use PersonalizeWP\Settings;
use PersonalizeWP\Admin\Admin;
use PersonalizeWP\Admin\Admin_Blocks;
use PersonalizeWP\Admin\Data_Export;

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

/**
 * The core plugin class.
 *
 * This is used to define internationalization, admin-specific hooks, and
 * public-facing site hooks.
 *
 * Also maintains the unique identifier of this plugin as well as the current
 * version of the plugin.
 *
 * @since      1.0.0
 * @package    PersonalizeWP
 */
final class PersonalizeWP {

	/**
	 * Holds the singleton instance of this class
	 *
	 * @since 3.2.0
	 * @var PersonalizeWP
	 */
	public static $instance = false;

	/**
	 * Setup flag to ensure only run once
	 *
	 * @since 2.5.0
	 *
	 * @var boolean
	 */
	private $is_setup = false;

	/**
	 * The unique identifier of this plugin.
	 *
	 * @since    1.0.0
	 * @access   protected
	 * @var      string    $personalizewp    The string used to uniquely identify this plugin.
	 */
	protected $personalizewp;

	/**
	 * The current version of the plugin.
	 *
	 * @since    1.0.0
	 * @access   protected
	 * @var      string    $version    The current version of the plugin.
	 */
	protected $version;

	/**
	 * URLs and Paths used by the plugin
	 *
	 * @since 1.2.0
	 *
	 * @var array
	 */
	public $locations = array();

	/**
	 * GEOIP Reader
	 *
	 * @since      1.0.0
	 * @deprecated 3.5.0 Use Geo_Service instead.
	 * @var object
	 */
	private $geo_reader;

	/**
	 * Cached subdivision data.
	 *
	 * @since 3.5.0
	 * @var array|null
	 */
	private $subdivisions_data = null;

	/**
	 * Cached untranslated subdivisions data for reverse lookups.
	 *
	 * @since 3.5.0
	 * @var array|null
	 */
	private $subdivisions_data_raw = null;

	/**
	 * Process DB operations such as migrations.
	 *
	 * @var DB_Manager
	 */
	public $database;

	/**
	 * Stores and manages WordPress settings.
	 *
	 * @since 2.0.0
	 * @var Settings
	 */
	public $settings;

	/**
	 * Holds and manages the REST API.
	 *
	 * @since 3.2.0
	 * @var Api
	 */
	public $api;

	/**
	 * Holds and manages the frontend.
	 *
	 * @since 3.2.0
	 * @var PublicFacing
	 */
	public $public;

	/**
	 * Holds and manages the admin area.
	 *
	 * @since 3.2.0
	 * @var Admin
	 */
	public $admin;

	/**
	 * Blocks Admin
	 *
	 * @since 3.2.0
	 * @var Admin_Blocks
	 */
	public $admin_blocks;

	/**
	 * Block rendering logic
	 *
	 * @since 3.2.0
	 * @var Block_Renderer
	 */
	public $block_renderer;

	/**
	 * Holds and manages all the tracking functionality.
	 *
	 * @since 3.2.0
	 *
	 * @var array
	 */
	public array $tracking;

	/**
	 * Holds and manages custom activity event types.
	 *
	 * @since 3.3.0
	 *
	 * @var array
	 */
	private array $activity_events = array();

	/**
	 * Initialises the instance
	 *
	 * Set the plugin name and the plugin version that can be used throughout the plugin.
	 *
	 * @since 1.0.0
	 *
	 * @param string $file Main plugin file
	 */
	private function __construct( $file ) {

		if ( defined( 'PERSONALIZEWP_VERSION' ) ) {
			$this->version = PERSONALIZEWP_VERSION;
		} else {
			$this->version = '1.0.0';
		}
		$this->personalizewp = 'personalizewp';

		$dir_path = plugin_dir_path( $file );
		$dir_url  = plugin_dir_url( $file );

		$this->locations = array(
			'file'    => $file,
			'dir'     => $dir_path,
			'url'     => $dir_url,
			'inc_dir' => $dir_path . 'includes/',
		);
	}

	/**
	 * Return the PersonalizeWP instance.
	 *
	 * @param string $file Main plugin file
	 * @return PersonalizeWP
	 */
	public static function instance( $file = null ) {
		if ( ! self::$instance && $file ) {
			self::$instance = new PersonalizeWP( $file );
		}

		return self::$instance;
	}

	/**
	 * Setup the initial hooks to fully load the plugin.
	 *
	 * @since 2.5.0
	 */
	public function setup() {

		// Don't double setup
		if ( $this->is_setup ) {
			return;
		}
		$this->is_setup = true;

		// Suppress Pro from loading fully.
		add_filter( 'personalizewp_pro_disable_loading', '__return_true' );

		// Need to early filter block args, due to many plugins loading before 'init'.
		add_filter( 'register_block_type_args', [ $this, 'add_pwp_block_args' ], 10, 2 );

		add_action( 'init', [ $this, 'init' ] );

		// Integrations often need very early hooks.
		$this->load_integrations();
	}

	/**
	 * Add the 'personalizewp' attribute, where our rules are stored, to dynamic blocks.
	 *
	 * We normally add the block attributes in the browser's JS env only, but many
	 * blocks use a ServerSideRender dynamic preview, so the PHP env needs
	 * to know about our new attribute(s), too.
	 *
	 * @since 3.0.2
	 *
	 * @param array  $settings  Array of settings for registering a block type.
	 * @param string $name      Block type name including namespace.
	 */
	public function add_pwp_block_args( $settings, $name ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed

		// Only add to blocks that already have attributes.
		if ( empty( $settings['attributes'] ) ) {
			return $settings;
		}

		/** This is necessary for `/wp-json/wp/v2/block-renderer` REST endpoint to not throw `rest_additional_properties_forbidden`. */
		$settings['attributes']['personalizewp'] = [
			'type' => 'object',
		];

		/**
		 * Filter PersonalizeWP added Block Supported Attributes for the Block Editor
		 *
		 * @since 1.0.0
		 *
		 * @param array $settings Block Type Args
		 */
		return apply_filters( 'personalizewp_register_block_type_args', $settings );
	}

	/**
	 * Initializes PersonalizeWP, in a i18n compatible way.
	 *
	 * Loads the dependencies, sets up the classes for the admin area and
	 * the public-facing side of the site. Then initializes add-ons
	 * and integrations with other plugins.
	 *
	 * @since  2.9.0
	 * @access public
	 *
	 * @return void
	 */
	public function init() {

		$this->load_dependencies();
		add_filter( 'cron_schedules', [ $this, 'register_cron_schedules' ] );

		if ( \is_admin() ) {
			$this->setup_admin();
		} elseif ( ! defined( 'DOING_CRON' ) ) {
			$this->setup_public();
		}

		add_action( 'wp', [ $this, 'schedule_events' ] );

		add_action( 'personalizewp_daily_purge_expired_activity_logs', [ $this, 'purge_expired_activity_logs' ] );
		add_action( 'personalizewp_daily_purge_expired_anonymous_profiles', [ $this, 'purge_expired_anonymous_profiles' ] );
		add_action( 'personalizewp_daily_purge_expired_known_profiles', [ $this, 'purge_expired_known_profiles' ] );
		add_action( 'personalizewp_daily_cleanup_export_files', [ $this, 'data_export_cleanup_old_export_files' ] );

		// Tracking classes for Activities/Contacts/Segments/ScoringRules
		$this->tracking = array(
			'exclusions'            => new Tracking\Exclusions(),
			'comments'              => new Tracking\Comments(),
			'user'                  => new Tracking\User(),
			'woocommerce'           => new Tracking\Woocommerce(),
			'segment/lead_score'    => new Segments\Lead_Score(),
			'segment/page'          => new Segments\Page_URL(),
			'segment/form'          => new Segments\Form(),
			'segment/referer'       => new Segments\Referer(),
			'segment/location'      => new Segments\Location(),
			'segment/query'         => new Segments\Query(),
			'segment/post-type'     => new Segments\Post_Type(),
			'segment/product'       => new Segments\Product(),
			'segment/taxonomy'      => new Segments\Taxonomy(),
			'scoring_rules/page'    => new Scoring_Rules\Page_URL(),
			'scoring_rules/form'    => new Scoring_Rules\Form(),
			'scoring_rules/product' => new Scoring_Rules\Product(),
		);
		foreach ( $this->tracking as $class ) {
			if ( method_exists( $class, 'setup' ) ) {
				$class->setup();
			}
		}

		// Register custom Editor blocks.
		$this->register_blocks();

		$this->create_initial_event_types();

		// Check for Pro specific hook, so as to force Pro to not load. Side effect, stops any other add-on from loading.
		if ( has_action( 'activate_personalizewp-pro/personalizewp-pro.php' ) ) {
			return;
		}

		/**
		 * Fires when PersonalizeWP has loaded.
		 *
		 * When developing Add-Ons, use this hook to initialize any functionality that depends on PersonalizeWP functionality.
		 *
		 * @since 2.0.0 Added the PersonalizeWP param
		 *
		 * @param PersonalizeWP $this The main PersonalizeWP object
		 */
		do_action( 'personalizewp_loaded', $this );
	}

	/**
	 * Initializes integrations with other plugins.
	 *
	 * @since  2.5.0
	 * @access private
	 *
	 * @return void
	 */
	private function load_integrations() {

		$integrations = glob( $this->plugin_path( 'includes/integrations/*.php' ) );
		foreach ( array_filter( $integrations, 'is_file' ) as $file_path ) {
			include_once $file_path;
		}

		/**
		 * Fires when PersonalizeWP is loading integrations
		 *
		 * When developing Add-Ons, use this hook to initialize any integration functionality.
		 *
		 * @since 2.5.0
		 *
		 * @param PersonalizeWP $this The main PersonalizeWP object
		 */
		do_action( 'personalizewp_register_integrations', $this );
	}

	/**
	 * Load the required dependencies for this plugin.
	 *
	 * @since  1.0.0
	 * @access private
	 */
	private function load_dependencies() {

		// Autoload packages
		require_once $this->plugin_path( 'vendor/autoload.php' );

		$this->database = DB_Manager::instance();
		$this->settings = Settings::instance();

		// API is used by public FE and admin.
		$this->api = API::instance();
		$this->api->setup();

		// Processing of blocks in admin can occur during REST calls.
		$this->admin_blocks = Admin_Blocks::instance();
		$this->admin_blocks->setup();

		// Geo database manager handles downloading and maintaining the MMDB file.
		Geo_Database_Manager::instance()->setup();
	}

	/**
	 * Register/initialise all of the classes and hooks related to the
	 * admin area functionality of the plugin.
	 *
	 * @since  2.5.0
	 * @access private
	 */
	private function setup_admin() {

		$this->admin = Admin::instance();
		$this->admin->setup();
	}

	/**
	 * Register/initialise all of the classes and hooks related to the
	 * public-facing functionality of the plugin, this includes REST API, even admin REST points.
	 *
	 * @since  2.5.0
	 * @access private
	 */
	private function setup_public() {

		$this->public = PublicFacing::instance();
		$this->public->setup();

		$this->block_renderer = Block_Renderer::instance();
		$this->block_renderer->setup();
	}

	/**
	 * Schedules our events.
	 *
	 * @since 3.2.0
	 */
	public function schedule_events() {
		$weekly_schedule = $this->get_weekly_schedule_name();

		if ( ! wp_next_scheduled( 'personalizewp_weekly_scheduled_events' ) ) {
			wp_schedule_event( time(), $weekly_schedule, 'personalizewp_weekly_scheduled_events' );
		}
		if ( ! wp_next_scheduled( 'personalizewp_daily_purge_expired_anonymous_profiles' ) ) {
			wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'personalizewp_daily_purge_expired_anonymous_profiles' );
		}
		if ( ! wp_next_scheduled( 'personalizewp_daily_purge_expired_known_profiles' ) ) {
			wp_schedule_event( time() + ( 2 * HOUR_IN_SECONDS ), 'daily', 'personalizewp_daily_purge_expired_known_profiles' );
		}
		if ( ! wp_next_scheduled( 'personalizewp_daily_purge_expired_activity_logs' ) ) {
			wp_schedule_event( time() + ( 3 * HOUR_IN_SECONDS ), 'daily', 'personalizewp_daily_purge_expired_activity_logs' );
		}
		if ( ! wp_next_scheduled( 'personalizewp_daily_cleanup_export_files' ) ) {
			wp_schedule_event( time(), 'daily', 'personalizewp_daily_cleanup_export_files' );
		}
		if ( ! wp_next_scheduled( Geo_Database_Manager::CRON_HOOK ) ) {
			wp_schedule_event( time(), $weekly_schedule, Geo_Database_Manager::CRON_HOOK );
		}
	}

	/**
	 * Register PersonalizeWP cron schedules.
	 *
	 * Adds a weekly fallback schedule for environments where the core `weekly`
	 * recurrence is unavailable or has been removed.
	 *
	 * @since 3.5.0
	 *
	 * @param array $schedules Existing cron schedules.
	 *
	 * @return array
	 */
	public function register_cron_schedules( $schedules ) {
		if ( ! isset( $schedules['personalizewp_weekly'] ) ) {
			$schedules['personalizewp_weekly'] = [
				'interval' => WEEK_IN_SECONDS,
				'display'  => __( 'Once Weekly (PersonalizeWP)', 'personalizewp' ),
			];
		}

		return $schedules;
	}

	/**
	 * Get the weekly recurrence name to use when scheduling events.
	 *
	 * @since 3.5.0
	 *
	 * @return string
	 */
	private function get_weekly_schedule_name() {
		$schedules = wp_get_schedules();

		return isset( $schedules['weekly'] ) ? 'weekly' : 'personalizewp_weekly';
	}

	/**
	 * Add block category for PersonalizeWP Blocks.
	 *
	 * @since 3.2.2
	 *
	 * @param array[] $categories All categories
	 *
	 * @return array[] Returns an array containing array of categories for block types including our custom ones.
	 */
	public function register_block_category( $categories ) {
		return array_merge(
			$categories,
			array(
				array(
					'slug'  => 'personalizewp',
					'title' => esc_html__( 'PersonalizeWP', 'personalizewp' ),
				),
			)
		);
	}

	/**
	 * Register custom block types.
	 *
	 * @since 3.2.0
	 */
	public function register_blocks() {

		add_filter( 'block_categories_all', [ $this, 'register_block_category' ], 10 );

		$custom_blocks = array(
			'product-collection',
			'variations-block',
			'variation',
			'variation-fallback',
		);

		foreach ( $custom_blocks as $block ) {
			register_block_type_from_metadata( $this->plugin_path( 'build/blocks/' . $block ) );
		}
	}

	/**
	 * Purge anonymous profiles with last seen activity logs beyond the retention period, if set.
	 *
	 * @since 3.2.0
	 */
	public function purge_expired_anonymous_profiles() {
		global $wpdb;

		$period = $this->get_setting( 'privacy_ttl_anonymous_profiles' );
		if ( empty( $period ) ) {
			return;
		}

		$date = ( new \DateTime( "- $period seconds" ) )->format( 'Y-m-d H:i:s' );

		// Select all unknown profile IDs with last_seen older than DATE.
		$ids = $wpdb->get_col(
			$wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}pwp_contacts WHERE is_known = 0 AND last_seen < %s", $date ) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
		);
		if ( empty( $ids ) ) {
			// Nothing to do.
			return;
		}

		$this->purge_profiles_with_ids( $ids );
	}

	/**
	 * Purge old Activity Export files.
	 *
	 * @since 3.3.0
	 */
	public function data_export_cleanup_old_export_files() {
		Data_Export::instance()->cleanup_old_export_files();
	}

	/**
	 * Purge known profiles with last seen activity logs beyond the retention period, if set.
	 *
	 * @since 3.2.0
	 */
	public function purge_expired_known_profiles() {
		global $wpdb;

		$period = $this->get_setting( 'privacy_ttl_known_profiles' );
		if ( empty( $period ) ) {
			return;
		}

		$date = ( new \DateTime( "- $period seconds" ) )->format( 'Y-m-d H:i:s' );

		// Select all known profile IDs with last_seen older than DATE.
		$ids = $wpdb->get_col(
			$wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}pwp_contacts WHERE is_known = 1 AND last_seen < %s", $date ) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
		);
		if ( empty( $ids ) ) {
			// Nothing to do.
			return;
		}

		$this->purge_profiles_with_ids( $ids );
	}

	/**
	 * Purge activity logs beyond the retention period, if set.
	 * Note: Ignores if the profiles are known or not.
	 *
	 * @since 3.2.0
	 */
	public function purge_expired_activity_logs() {
		global $wpdb;

		$period = $this->get_setting( 'privacy_ttl_activities' );
		if ( empty( $period ) ) {
			return;
		}

		$date = ( new \DateTime( "- $period seconds" ) )->format( 'Y-m-d H:i:s' );
		$wpdb->query(
			// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: custom db table
			// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: inputs sanitised/validated above
			$wpdb->prepare(
				"DELETE {$wpdb->prefix}pwp_activity, {$wpdb->prefix}pwp_activity_meta FROM {$wpdb->prefix}pwp_activity_meta
				INNER JOIN {$wpdb->prefix}pwp_activity ON {$wpdb->prefix}pwp_activity.ID = {$wpdb->prefix}pwp_activity_meta.activity_id
				WHERE {$wpdb->prefix}pwp_activity.created < %s",
				$date
			) // Single SQL to delete the activity items and attached meta
			// phpcs:enable
		);

		// TBA: Sort out cache flushing
	}

	/**
	 * Purge profiles with specific IDs.
	 *
	 * @since 3.2.0
	 *
	 * @param array $ids Profile IDs
	 *
	 * @return boolean
	 */
	private function purge_profiles_with_ids( $ids ) {
		global $wpdb;

		// Sanitise IDs.
		$ids = array_unique( array_filter( array_map( 'intval', $ids ) ) );

		if ( empty( $ids ) ) {
			return false;
		}

		// Delete all activity entries with those profile IDs, joined with meta to delete them at the same time.
		$wpdb->query(
			$wpdb->prepare(
				sprintf(
					"DELETE {$wpdb->prefix}pwp_activity, {$wpdb->prefix}pwp_activity_meta FROM {$wpdb->prefix}pwp_activity_meta
					INNER JOIN {$wpdb->prefix}pwp_activity ON {$wpdb->prefix}pwp_activity.ID = {$wpdb->prefix}pwp_activity_meta.activity_id
					WHERE {$wpdb->prefix}pwp_activity.contact_id IN (%s)",
					implode( ',', array_fill( 0, count( $ids ), '%d' ) )
				),
				$ids
			)
		);

		// Delete all profile meta entries with those profile IDs.
		$wpdb->query(
			$wpdb->prepare(
				sprintf(
					"DELETE FROM {$wpdb->prefix}pwp_contacts_meta WHERE contact_id IN (%s)",
					implode( ',', array_fill( 0, count( $ids ), '%d' ) )
				),
				$ids
			)
		);

		// Delete all profiles with those IDs.
		$wpdb->query(
			$wpdb->prepare(
				sprintf(
					"DELETE FROM {$wpdb->prefix}pwp_contacts WHERE ID IN (%s)",
					implode( ',', array_fill( 0, count( $ids ), '%d' ) )
				),
				$ids
			)
		);

		// TBA: Sort out cache flushing

		// Clear out the various Contacts caches since data has changed.
		wp_cache_delete_multiple( $ids, 'pwp_pro_contacts' );
		wp_cache_delete_multiple( $ids, 'pwp-profiles_meta' );
		wp_cache_flush_group( 'pwp_pro_contacts-uid' );

		return true;
	}

	/**
	 * Convert an IP Address into a two letter country code following ISO 3166-1.
	 *
	 * @since      1.0.0
	 * @deprecated 3.5.0 Use Geo_Service::instance()->get_country() instead.
	 *
	 * @param string $ip_address IPv4 or IPv6 address as a string
	 *
	 * @return string ISOCode on success, empty string otherwise
	 */
	public function convert_ip_to_isocode( $ip_address = '' ) {
		_deprecated_function( __METHOD__, '3.5.0', 'PersonalizeWP\Geo_Service::instance()->get_country()' );

		return Geo_Service::instance()->get_country( $ip_address );
	}

	/**
	 * Return all plugin options, or optionally just a single option.
	 *
	 * @since 2.0.0
	 *
	 * @param string $option Individual option to return, or empty to return all
	 *
	 * @return mixed
	 */
	public function get_setting( $option = '' ) {

		if ( empty( $option ) ) {
			return $this->settings->get_options();
		}

		return $this->settings->get_option( $option );
	}

	/**
	 * Return the PersonalizeWP supported Countries
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	public function get_countries() {

		return [
			'AF' => _x( 'Afghanistan', 'countries', 'personalizewp' ),
			'AX' => _x( 'Åland Islands', 'countries', 'personalizewp' ),
			'AL' => _x( 'Albania', 'countries', 'personalizewp' ),
			'DZ' => _x( 'Algeria', 'countries', 'personalizewp' ),
			'AS' => _x( 'American Samoa', 'countries', 'personalizewp' ),
			'AD' => _x( 'Andorra', 'countries', 'personalizewp' ),
			'AO' => _x( 'Angola', 'countries', 'personalizewp' ),
			'AI' => _x( 'Anguilla', 'countries', 'personalizewp' ),
			'AQ' => _x( 'Antarctica', 'countries', 'personalizewp' ),
			'AG' => _x( 'Antigua and Barbuda', 'countries', 'personalizewp' ),
			'AR' => _x( 'Argentina', 'countries', 'personalizewp' ),
			'AM' => _x( 'Armenia', 'countries', 'personalizewp' ),
			'AW' => _x( 'Aruba', 'countries', 'personalizewp' ),
			'AU' => _x( 'Australia', 'countries', 'personalizewp' ),
			'AT' => _x( 'Austria', 'countries', 'personalizewp' ),
			'AZ' => _x( 'Azerbaijan', 'countries', 'personalizewp' ),
			'BS' => _x( 'Bahamas', 'countries', 'personalizewp' ),
			'BH' => _x( 'Bahrain', 'countries', 'personalizewp' ),
			'BD' => _x( 'Bangladesh', 'countries', 'personalizewp' ),
			'BB' => _x( 'Barbados', 'countries', 'personalizewp' ),
			'BY' => _x( 'Belarus', 'countries', 'personalizewp' ),
			'BE' => _x( 'Belgium', 'countries', 'personalizewp' ),
			'BZ' => _x( 'Belize', 'countries', 'personalizewp' ),
			'BJ' => _x( 'Benin', 'countries', 'personalizewp' ),
			'BM' => _x( 'Bermuda', 'countries', 'personalizewp' ),
			'BT' => _x( 'Bhutan', 'countries', 'personalizewp' ),
			'BO' => _x( 'Bolivia, Plurinational State of', 'countries', 'personalizewp' ),
			'BA' => _x( 'Bosnia and Herzegovina', 'countries', 'personalizewp' ),
			'BW' => _x( 'Botswana', 'countries', 'personalizewp' ),
			'BV' => _x( 'Bouvet Island', 'countries', 'personalizewp' ),
			'BR' => _x( 'Brazil', 'countries', 'personalizewp' ),
			'IO' => _x( 'British Indian Ocean Territory', 'countries', 'personalizewp' ),
			'BN' => _x( 'Brunei Darussalam', 'countries', 'personalizewp' ),
			'BG' => _x( 'Bulgaria', 'countries', 'personalizewp' ),
			'BF' => _x( 'Burkina Faso', 'countries', 'personalizewp' ),
			'BI' => _x( 'Burundi', 'countries', 'personalizewp' ),
			'KH' => _x( 'Cambodia', 'countries', 'personalizewp' ),
			'CM' => _x( 'Cameroon', 'countries', 'personalizewp' ),
			'CA' => _x( 'Canada', 'countries', 'personalizewp' ),
			'CV' => _x( 'Cape Verde', 'countries', 'personalizewp' ),
			'KY' => _x( 'Cayman Islands', 'countries', 'personalizewp' ),
			'CF' => _x( 'Central African Republic', 'countries', 'personalizewp' ),
			'TD' => _x( 'Chad', 'countries', 'personalizewp' ),
			'CL' => _x( 'Chile', 'countries', 'personalizewp' ),
			'CN' => _x( 'China', 'countries', 'personalizewp' ),
			'CX' => _x( 'Christmas Island', 'countries', 'personalizewp' ),
			'CC' => _x( 'Cocos (Keeling) Islands', 'countries', 'personalizewp' ),
			'CO' => _x( 'Colombia', 'countries', 'personalizewp' ),
			'KM' => _x( 'Comoros', 'countries', 'personalizewp' ),
			'CG' => _x( 'Congo', 'countries', 'personalizewp' ),
			'CD' => _x( 'Congo, Democratic Republic', 'countries', 'personalizewp' ),
			'CK' => _x( 'Cook Islands', 'countries', 'personalizewp' ),
			'CR' => _x( 'Costa Rica', 'countries', 'personalizewp' ),
			'CI' => _x( "Côte d'Ivoire", 'countries', 'personalizewp' ),
			'HR' => _x( 'Croatia', 'countries', 'personalizewp' ),
			'CU' => _x( 'Cuba', 'countries', 'personalizewp' ),
			'CY' => _x( 'Cyprus', 'countries', 'personalizewp' ),
			'CZ' => _x( 'Czech Republic', 'countries', 'personalizewp' ),
			'DK' => _x( 'Denmark', 'countries', 'personalizewp' ),
			'DJ' => _x( 'Djibouti', 'countries', 'personalizewp' ),
			'DM' => _x( 'Dominica', 'countries', 'personalizewp' ),
			'DO' => _x( 'Dominican Republic', 'countries', 'personalizewp' ),
			'EC' => _x( 'Ecuador', 'countries', 'personalizewp' ),
			'EG' => _x( 'Egypt', 'countries', 'personalizewp' ),
			'SV' => _x( 'El Salvador', 'countries', 'personalizewp' ),
			'GQ' => _x( 'Equatorial Guinea', 'countries', 'personalizewp' ),
			'ER' => _x( 'Eritrea', 'countries', 'personalizewp' ),
			'EE' => _x( 'Estonia', 'countries', 'personalizewp' ),
			'ET' => _x( 'Ethiopia', 'countries', 'personalizewp' ),
			'FK' => _x( 'Falkland Islands (Malvinas)', 'countries', 'personalizewp' ),
			'FO' => _x( 'Faroe Islands', 'countries', 'personalizewp' ),
			'FJ' => _x( 'Fiji', 'countries', 'personalizewp' ),
			'FI' => _x( 'Finland', 'countries', 'personalizewp' ),
			'FR' => _x( 'France', 'countries', 'personalizewp' ),
			'GF' => _x( 'French Guiana', 'countries', 'personalizewp' ),
			'PF' => _x( 'French Polynesia', 'countries', 'personalizewp' ),
			'TF' => _x( 'French Southern Territories', 'countries', 'personalizewp' ),
			'GA' => _x( 'Gabon', 'countries', 'personalizewp' ),
			'GM' => _x( 'Gambia', 'countries', 'personalizewp' ),
			'GE' => _x( 'Georgia', 'countries', 'personalizewp' ),
			'DE' => _x( 'Germany', 'countries', 'personalizewp' ),
			'GH' => _x( 'Ghana', 'countries', 'personalizewp' ),
			'GI' => _x( 'Gibraltar', 'countries', 'personalizewp' ),
			'GR' => _x( 'Greece', 'countries', 'personalizewp' ),
			'GL' => _x( 'Greenland', 'countries', 'personalizewp' ),
			'GD' => _x( 'Grenada', 'countries', 'personalizewp' ),
			'GP' => _x( 'Guadeloupe', 'countries', 'personalizewp' ),
			'GU' => _x( 'Guam', 'countries', 'personalizewp' ),
			'GT' => _x( 'Guatemala', 'countries', 'personalizewp' ),
			'GG' => _x( 'Guernsey', 'countries', 'personalizewp' ),
			'GN' => _x( 'Guinea', 'countries', 'personalizewp' ),
			'GW' => _x( 'Guinea-Bissau', 'countries', 'personalizewp' ),
			'GY' => _x( 'Guyana', 'countries', 'personalizewp' ),
			'HT' => _x( 'Haiti', 'countries', 'personalizewp' ),
			'HM' => _x( 'Heard Island & Mcdonald Islands', 'countries', 'personalizewp' ),
			'VA' => _x( 'Holy See (Vatican City State)', 'countries', 'personalizewp' ),
			'HN' => _x( 'Honduras', 'countries', 'personalizewp' ),
			'HK' => _x( 'Hong Kong', 'countries', 'personalizewp' ),
			'HU' => _x( 'Hungary', 'countries', 'personalizewp' ),
			'IS' => _x( 'Iceland', 'countries', 'personalizewp' ),
			'IN' => _x( 'India', 'countries', 'personalizewp' ),
			'ID' => _x( 'Indonesia', 'countries', 'personalizewp' ),
			'IR' => _x( 'Iran, Islamic Republic Of', 'countries', 'personalizewp' ),
			'IQ' => _x( 'Iraq', 'countries', 'personalizewp' ),
			'IE' => _x( 'Ireland', 'countries', 'personalizewp' ),
			'IM' => _x( 'Isle Of Man', 'countries', 'personalizewp' ),
			'IL' => _x( 'Israel', 'countries', 'personalizewp' ),
			'IT' => _x( 'Italy', 'countries', 'personalizewp' ),
			'JM' => _x( 'Jamaica', 'countries', 'personalizewp' ),
			'JP' => _x( 'Japan', 'countries', 'personalizewp' ),
			'JE' => _x( 'Jersey', 'countries', 'personalizewp' ),
			'JO' => _x( 'Jordan', 'countries', 'personalizewp' ),
			'KZ' => _x( 'Kazakhstan', 'countries', 'personalizewp' ),
			'KE' => _x( 'Kenya', 'countries', 'personalizewp' ),
			'KI' => _x( 'Kiribati', 'countries', 'personalizewp' ),
			'KP' => _x( "Korea, Democratic People's Republic of", 'countries', 'personalizewp' ),
			'KR' => _x( 'Korea, Republic of', 'countries', 'personalizewp' ),
			'KW' => _x( 'Kuwait', 'countries', 'personalizewp' ),
			'KG' => _x( 'Kyrgyzstan', 'countries', 'personalizewp' ),
			'LA' => _x( "Lao People's Democratic Republic", 'countries', 'personalizewp' ),
			'LV' => _x( 'Latvia', 'countries', 'personalizewp' ),
			'LB' => _x( 'Lebanon', 'countries', 'personalizewp' ),
			'LS' => _x( 'Lesotho', 'countries', 'personalizewp' ),
			'LR' => _x( 'Liberia', 'countries', 'personalizewp' ),
			'LY' => _x( 'Libyan Arab Jamahiriya', 'countries', 'personalizewp' ),
			'LI' => _x( 'Liechtenstein', 'countries', 'personalizewp' ),
			'LT' => _x( 'Lithuania', 'countries', 'personalizewp' ),
			'LU' => _x( 'Luxembourg', 'countries', 'personalizewp' ),
			'MO' => _x( 'Macao', 'countries', 'personalizewp' ),
			'MK' => _x( 'Macedonia, the former Yugoslav Republic of', 'countries', 'personalizewp' ),
			'MG' => _x( 'Madagascar', 'countries', 'personalizewp' ),
			'MW' => _x( 'Malawi', 'countries', 'personalizewp' ),
			'MY' => _x( 'Malaysia', 'countries', 'personalizewp' ),
			'MV' => _x( 'Maldives', 'countries', 'personalizewp' ),
			'ML' => _x( 'Mali', 'countries', 'personalizewp' ),
			'MT' => _x( 'Malta', 'countries', 'personalizewp' ),
			'MH' => _x( 'Marshall Islands', 'countries', 'personalizewp' ),
			'MQ' => _x( 'Martinique', 'countries', 'personalizewp' ),
			'MR' => _x( 'Mauritania', 'countries', 'personalizewp' ),
			'MU' => _x( 'Mauritius', 'countries', 'personalizewp' ),
			'YT' => _x( 'Mayotte', 'countries', 'personalizewp' ),
			'MX' => _x( 'Mexico', 'countries', 'personalizewp' ),
			'FM' => _x( 'Micronesia, Federated States Of', 'countries', 'personalizewp' ),
			'MD' => _x( 'Moldova, Republic of', 'countries', 'personalizewp' ),
			'MC' => _x( 'Monaco', 'countries', 'personalizewp' ),
			'MN' => _x( 'Mongolia', 'countries', 'personalizewp' ),
			'ME' => _x( 'Montenegro', 'countries', 'personalizewp' ),
			'MS' => _x( 'Montserrat', 'countries', 'personalizewp' ),
			'MA' => _x( 'Morocco', 'countries', 'personalizewp' ),
			'MZ' => _x( 'Mozambique', 'countries', 'personalizewp' ),
			'MM' => _x( 'Myanmar', 'countries', 'personalizewp' ),
			'NA' => _x( 'Namibia', 'countries', 'personalizewp' ),
			'NR' => _x( 'Nauru', 'countries', 'personalizewp' ),
			'NP' => _x( 'Nepal', 'countries', 'personalizewp' ),
			'NL' => _x( 'Netherlands', 'countries', 'personalizewp' ),
			'AN' => _x( 'Netherlands Antilles', 'countries', 'personalizewp' ),
			'NC' => _x( 'New Caledonia', 'countries', 'personalizewp' ),
			'NZ' => _x( 'New Zealand', 'countries', 'personalizewp' ),
			'NI' => _x( 'Nicaragua', 'countries', 'personalizewp' ),
			'NE' => _x( 'Niger', 'countries', 'personalizewp' ),
			'NG' => _x( 'Nigeria', 'countries', 'personalizewp' ),
			'NU' => _x( 'Niue', 'countries', 'personalizewp' ),
			'NF' => _x( 'Norfolk Island', 'countries', 'personalizewp' ),
			'MP' => _x( 'Northern Mariana Islands', 'countries', 'personalizewp' ),
			'NO' => _x( 'Norway', 'countries', 'personalizewp' ),
			'OM' => _x( 'Oman', 'countries', 'personalizewp' ),
			'PK' => _x( 'Pakistan', 'countries', 'personalizewp' ),
			'PW' => _x( 'Palau', 'countries', 'personalizewp' ),
			'PS' => _x( 'Palestinian Territory, Occupied', 'countries', 'personalizewp' ),
			'PA' => _x( 'Panama', 'countries', 'personalizewp' ),
			'PG' => _x( 'Papua New Guinea', 'countries', 'personalizewp' ),
			'PY' => _x( 'Paraguay', 'countries', 'personalizewp' ),
			'PE' => _x( 'Peru', 'countries', 'personalizewp' ),
			'PH' => _x( 'Philippines', 'countries', 'personalizewp' ),
			'PN' => _x( 'Pitcairn', 'countries', 'personalizewp' ),
			'PL' => _x( 'Poland', 'countries', 'personalizewp' ),
			'PT' => _x( 'Portugal', 'countries', 'personalizewp' ),
			'PR' => _x( 'Puerto Rico', 'countries', 'personalizewp' ),
			'QA' => _x( 'Qatar', 'countries', 'personalizewp' ),
			'RE' => _x( 'Réunion', 'countries', 'personalizewp' ),
			'RO' => _x( 'Romania', 'countries', 'personalizewp' ),
			'RU' => _x( 'Russian Federation', 'countries', 'personalizewp' ),
			'RW' => _x( 'Rwanda', 'countries', 'personalizewp' ),
			'BL' => _x( 'Saint Barthélemy', 'countries', 'personalizewp' ),
			'SH' => _x( 'Saint Helena, Ascension and Tristan da Cunha', 'countries', 'personalizewp' ),
			'KN' => _x( 'Saint Kitts and Nevis', 'countries', 'personalizewp' ),
			'LC' => _x( 'Saint Lucia', 'countries', 'personalizewp' ),
			'MF' => _x( 'Saint Martin (French part)', 'countries', 'personalizewp' ),
			'PM' => _x( 'Saint Pierre and Miquelon', 'countries', 'personalizewp' ),
			'VC' => _x( 'Saint Vincent and the Grenadines', 'countries', 'personalizewp' ),
			'WS' => _x( 'Samoa', 'countries', 'personalizewp' ),
			'SM' => _x( 'San Marino', 'countries', 'personalizewp' ),
			'ST' => _x( 'Sao Tome And Principe', 'countries', 'personalizewp' ),
			'SA' => _x( 'Saudi Arabia', 'countries', 'personalizewp' ),
			'SN' => _x( 'Senegal', 'countries', 'personalizewp' ),
			'RS' => _x( 'Serbia', 'countries', 'personalizewp' ),
			'SC' => _x( 'Seychelles', 'countries', 'personalizewp' ),
			'SL' => _x( 'Sierra Leone', 'countries', 'personalizewp' ),
			'SG' => _x( 'Singapore', 'countries', 'personalizewp' ),
			'SK' => _x( 'Slovakia', 'countries', 'personalizewp' ),
			'SI' => _x( 'Slovenia', 'countries', 'personalizewp' ),
			'SB' => _x( 'Solomon Islands', 'countries', 'personalizewp' ),
			'SO' => _x( 'Somalia', 'countries', 'personalizewp' ),
			'ZA' => _x( 'South Africa', 'countries', 'personalizewp' ),
			'GS' => _x( 'South Georgia And Sandwich Isl.', 'countries', 'personalizewp' ),
			'ES' => _x( 'Spain', 'countries', 'personalizewp' ),
			'LK' => _x( 'Sri Lanka', 'countries', 'personalizewp' ),
			'SD' => _x( 'Sudan', 'countries', 'personalizewp' ),
			'SR' => _x( 'Suriname', 'countries', 'personalizewp' ),
			'SJ' => _x( 'Svalbard And Jan Mayen', 'countries', 'personalizewp' ),
			'SZ' => _x( 'Swaziland', 'countries', 'personalizewp' ),
			'SE' => _x( 'Sweden', 'countries', 'personalizewp' ),
			'CH' => _x( 'Switzerland', 'countries', 'personalizewp' ),
			'SY' => _x( 'Syrian Arab Republic', 'countries', 'personalizewp' ),
			'TW' => _x( 'Taiwan', 'countries', 'personalizewp' ),
			'TJ' => _x( 'Tajikistan', 'countries', 'personalizewp' ),
			'TZ' => _x( 'Tanzania, United Republic of', 'countries', 'personalizewp' ),
			'TH' => _x( 'Thailand', 'countries', 'personalizewp' ),
			'TL' => _x( 'Timor-Leste', 'countries', 'personalizewp' ),
			'TG' => _x( 'Togo', 'countries', 'personalizewp' ),
			'TK' => _x( 'Tokelau', 'countries', 'personalizewp' ),
			'TO' => _x( 'Tonga', 'countries', 'personalizewp' ),
			'TT' => _x( 'Trinidad And Tobago', 'countries', 'personalizewp' ),
			'TN' => _x( 'Tunisia', 'countries', 'personalizewp' ),
			'TR' => _x( 'Turkey', 'countries', 'personalizewp' ),
			'TM' => _x( 'Turkmenistan', 'countries', 'personalizewp' ),
			'TC' => _x( 'Turks And Caicos Islands', 'countries', 'personalizewp' ),
			'TV' => _x( 'Tuvalu', 'countries', 'personalizewp' ),
			'UG' => _x( 'Uganda', 'countries', 'personalizewp' ),
			'UA' => _x( 'Ukraine', 'countries', 'personalizewp' ),
			'AE' => _x( 'United Arab Emirates', 'countries', 'personalizewp' ),
			'GB' => _x( 'United Kingdom', 'countries', 'personalizewp' ),
			'US' => _x( 'United States', 'countries', 'personalizewp' ),
			'UM' => _x( 'United States Outlying Islands', 'countries', 'personalizewp' ),
			'UY' => _x( 'Uruguay', 'countries', 'personalizewp' ),
			'UZ' => _x( 'Uzbekistan', 'countries', 'personalizewp' ),
			'VU' => _x( 'Vanuatu', 'countries', 'personalizewp' ),
			'VE' => _x( 'Venezuela, Bolivarian Republic of', 'countries', 'personalizewp' ),
			'VN' => _x( 'Viet Nam', 'countries', 'personalizewp' ),
			'VG' => _x( 'Virgin Islands, British', 'countries', 'personalizewp' ),
			'VI' => _x( 'Virgin Islands, U.S.', 'countries', 'personalizewp' ),
			'WF' => _x( 'Wallis and Futuna', 'countries', 'personalizewp' ),
			'EH' => _x( 'Western Sahara', 'countries', 'personalizewp' ),
			'YE' => _x( 'Yemen', 'countries', 'personalizewp' ),
			'ZM' => _x( 'Zambia', 'countries', 'personalizewp' ),
			'ZW' => _x( 'Zimbabwe', 'countries', 'personalizewp' ),
		];
	}

	/**
	 * Return the PersonalizeWP supported Subdivisions (states, provinces, regions).
	 *
	 * @since 3.5.0
	 *
	 * @param string $country_code Optional. ISO 3166-1 country code to get subdivisions for.
	 * @param bool   $raw          Optional. If true, returns untranslated English names
	 *                             for use in reverse lookups against MMDB data.
	 *
	 * @return array Associative array of subdivision code => name. If no country code,
	 *               returns nested array keyed by country code.
	 */
	public function get_subdivisions( $country_code = '', $raw = false ) {

		if ( $raw ) {
			if ( null === $this->subdivisions_data_raw ) {
				$this->subdivisions_data_raw = $this->load_raw_subdivisions_data();
			}
			$data = $this->subdivisions_data_raw;
		} else {
			if ( null === $this->subdivisions_data ) {
				$this->subdivisions_data = include $this->plugin_path( 'includes/data/subdivisions.php' );

				/**
				 * Filters the subdivisions data.
				 *
				 * @since 3.5.0
				 *
				 * @param array $subdivisions Nested array of country code => [ subdivision code => name ].
				 */
				$this->subdivisions_data = apply_filters( 'personalizewp_subdivisions', $this->subdivisions_data );
			}
			$data = $this->subdivisions_data;
		}

		if ( ! empty( $country_code ) ) {
			return $data[ strtoupper( $country_code ) ] ?? [];
		}

		return $data;
	}

	/**
	 * Load untranslated subdivision labels directly from the data source file.
	 *
	 * This avoids relying on `switch_to_locale( 'en_US' )`, which may not be
	 * available on installs that do not have English locale packs present.
	 *
	 * @since 3.5.0
	 *
	 * @return array
	 */
	private function load_raw_subdivisions_data() {
		$file_contents = file_get_contents( $this->plugin_path( 'includes/data/subdivisions.php' ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
		if ( false === $file_contents ) {
			return [];
		}

		$data            = [];
		$current_country = '';
		$lines           = preg_split( "/\R/", $file_contents );

		foreach ( $lines as $line ) {
			if ( preg_match( "/^\s'([A-Z]{2})' => \[$/", $line, $matches ) ) {
				$current_country          = $matches[1];
				$data[ $current_country ] = [];
				continue;
			}

			if ( '' !== $current_country && preg_match( "/^\s+'([^']+)' => __\(\s*'((?:\\\\'|[^'])*)', 'personalizewp' \),$/", $line, $matches ) ) {
				$data[ $current_country ][ $matches[1] ] = stripcslashes( $matches[2] );
				continue;
			}

			if ( '' !== $current_country && preg_match( '/^\s],$/', $line ) ) {
				$current_country = '';
			}
		}

		return $data;
	}

	/**
	 * Returns the filesystem path for a file/dir within this plugin.
	 *
	 * @since 2.5.0
	 * @param string $file The path within this plugin, e.g. '/includes/integrations'
	 *
	 * @return string Filesystem path
	 */
	public function plugin_path( $file = '' ) {
		return $this->locations['dir'] . ltrim( $file, '/' );
	}

	/**
	 * Returns the URL path for a file/dir within this plugin.
	 *
	 * @since 2.6.0
	 * @param string $file The path within this plugin, e.g. '/public/js'
	 *
	 * @return string Filesystem path
	 */
	public function plugin_url( $file = '' ) {
		return $this->locations['url'] . ltrim( $file, '/' );
	}

	/**
	 * The name of the plugin used to uniquely identify it within the context of
	 * WordPress and to define internationalization functionality.
	 *
	 * @since     1.0.0
	 * @return    string    The name of the plugin.
	 */
	public function get_personalizewp() {
		return $this->personalizewp;
	}

	/**
	 * Retrieve the version number of the plugin.
	 *
	 * @since     1.0.0
	 * @return    string    The version number of the plugin.
	 */
	public function get_version() {
		return $this->version;
	}

	/**
	 * Check if tracking visitors should remain anonymous or not.
	 *
	 * For use by all tracking functionality, segments, integrations etc.
	 *
	 * @since 3.2.0
	 *
	 * @return bool
	 */
	public function should_anonymise_profiles(): bool {

		return (bool) $this->get_setting( 'privacy_anonymise_profiles' );
	}

	/**
	 * Check if we should be tracking anonymous visitors or not.
	 *
	 * For use by all tracking functionality, segments, integrations etc.
	 *
	 * @since 3.2.0
	 *
	 * @return bool
	 */
	public function should_track_anonymous_users(): bool {

		return (bool) $this->get_setting( 'profile_track_anonymous_users' );
	}

	/**
	 * Registers an event type.
	 *
	 * Note: Event type registrations should not be hooked before the
	 * {@see 'personalizewp_loaded'} action.
	 *
	 * @since 3.3.0
	 *
	 * @param string $event_type Event type key. Must not exceed 20 characters and may only contain
	 *                           lowercase alphanumeric characters, dashes, and underscores. See sanitize_key().
	 * @param array  $args {
	 *     Array or string of arguments for registering an event type.
	 *
	 *     @type string $label   Name of the event type shown in the recent events list.
	 * }
	 *
	 * @return bool|WP_Error True on successful event success, WP_Error object on failure.
	 */
	public function register_event_type( $event_type, $args = array() ) {

		// Sanitize post type name.
		$event_type = sanitize_key( $event_type );

		if ( empty( $event_type ) || strlen( $event_type ) > 20 ) {
			_doing_it_wrong( __FUNCTION__, __( 'Event type names must be between 1 and 20 characters in length.', 'personalizewp' ), '3.3.0' );
			return new \WP_Error( 'personalizewp_event_type_length_invalid', __( 'Event type names must be between 1 and 20 characters in length.', 'personalizewp' ) );
		}

		if ( isset( $this->activity_events[ $event_type ] ) ) {
			_doing_it_wrong( __FUNCTION__, __( 'Event type already registered.', 'personalizewp' ), '3.3.0' );
			return new \WP_Error( 'personalizewpevent_type_name_invalid', __( 'Event type already registered.', 'personalizewp' ) );
		}

		$args = wp_parse_args(
			$args,
			array(
				'name'  => $event_type,
				'label' => ucwords( str_replace( '-', ' ', $event_type ) ),
			)
		);

		$this->activity_events[ $event_type ] = $args;

		return true;
	}

	/**
	 * Returns array of all registered activity event types.
	 *
	 * @since 3.3.0
	 *
	 * @return array
	 */
	public function get_registered_event_types() {
		return $this->activity_events;
	}

	/**
	 * Creates the initial event types when 'init' action is fired.
	 *
	 * @since 3.3.0
	 */
	public function create_initial_event_types() {

		$this->register_event_type(
			'error404',
			array(
				'label' => __( '404 Error', 'personalizewp' ),
			)
		);

		$this->register_event_type(
			'post',
			array(
				'label' => __( 'Page visit', 'personalizewp' ),
			)
		);

		$this->register_event_type(
			'home',
			array(
				'label' => __( 'Home Page View', 'personalizewp' ),
			)
		);

		$this->register_event_type(
			'search',
			array(
				'label' => __( 'Search', 'personalizewp' ),
			)
		);

		$this->register_event_type(
			'login',
			array(
				'label' => __( 'User login', 'personalizewp' ),
			)
		);

		$this->register_event_type(
			'comment',
			array(
				'label' => __( 'Comment submission', 'personalizewp' ),
			)
		);

		$this->register_event_type(
			'form',
			array(
				'label' => __( 'Form submission', 'personalizewp' ),
			)
		);

		$this->register_event_type(
			'purchase',
			array(
				'label' => __( 'Purchased Product', 'personalizewp' ),
			)
		);

		$this->register_event_type(
			'tax',
			array(
				'label' => __( 'Category / Tag View', 'personalizewp' ),
			)
		);

		$this->register_event_type(
			'misc',
			array(
				'label' => __( 'Unknown', 'personalizewp' ),
			)
		);
	}
}
