<?php
/**
 * Otter Dashboard.
 *
 * @package ThemeIsle\GutenbergBlocks\Plugins
 */

namespace ThemeIsle\GutenbergBlocks\Plugins;

use ThemeIsle\GutenbergBlocks\Pro;
use ThemeIsle\GutenbergBlocks\Plugins\FSE_Onboarding;
use ThemeIsle\GutenbergBlocks\Plugins\Template_Cloud;

/**
 * Class Dashboard
 */
class Dashboard {

	/**
	 * The main instance var.
	 *
	 * @var Dashboard|null
	 */
	protected static $instance = null;

	/**
	 * Initialize the class
	 */
	public function init() {
		add_action( 'admin_menu', array( $this, 'register_menu_page' ) );
		add_action( 'admin_init', array( $this, 'maybe_redirect' ) );
		add_action( 'admin_head', array( $this, 'survey_elements' ) );
		add_action( 'admin_notices', array( $this, 'form_submission_elements' ), 30 );
		add_action( 'admin_head', array( $this, 'add_inline_css' ) );

		$form_options = get_option( 'themeisle_blocks_form_emails' );
		if ( ! empty( $form_options ) ) {
			add_action( 'wp_dashboard_setup', array( $this, 'form_submissions_widget' ) );
		}

		add_filter( 'themeisle-sdk/survey/' . OTTER_PRODUCT_SLUG, array( __CLASS__, 'get_survey_metadata' ), 10, 2 );
	}

	/**
	 * Register Admin Page
	 *
	 * @since   1.7.1
	 * @access  public
	 */
	public function register_menu_page() {
		$otter_icon = 'data:image/svg+xml;base64, ';

		$page_hook_suffix = add_menu_page(
			__( 'Otter Blocks', 'otter-blocks' ),
			__( 'Otter Blocks', 'otter-blocks' ),
			'manage_options',
			'otter',
			array( $this, 'menu_callback' ),
			$otter_icon
		);

		add_action( "admin_print_scripts-$page_hook_suffix", array( $this, 'enqueue_options_assets' ) );

		/**
		 * Add shortcut to the Blocks tab in Dashboard.
		 */


		add_submenu_page(
			'otter',
			__( 'Settings', 'otter-blocks' ),
			__( 'Settings', 'otter-blocks' ),
			'manage_options',
			'otter'
		);

		add_submenu_page(
			'otter',
			__( 'Submissions', 'otter-blocks' ),
			sprintf(
				'<div class="o-menu-submissions">%s <span class="o-menu-badge">%s</span></div>',
				esc_html__( 'Submissions', 'otter-blocks' ),
				esc_html__( 'Pro', 'otter-blocks' )
			),
			'manage_options',
			'form-submissions-free',
			array( $this, 'form_submissions_callback' ),
			10
		);

		add_submenu_page(
			'otter',
			__( 'Blocks', 'otter-blocks' ),
			__( 'Blocks', 'otter-blocks' ),
			'manage_options',
			'otter-blocks-toggle',
			function () {
				echo '<p>Redirecting...</p>
				<script>document.location.href = "/wp-admin/admin.php?page=otter#blocks";</script>';
			}
		);
	}

	/**
	 * Add inline CSS.
	 */
	public function add_inline_css() {
		?>
		<style>
			.o-menu-submissions {
				display: flex;
				align-items: center;
			}

			.o-menu-badge {
				border: 1px solid;
				border-radius: 16px;
				color: inherit;
				font-size: 10px;
				font-weight: 600;
				line-height: 8px;
				margin: 0;
				opacity: .8;
				padding: 4px 6px;
				text-transform: uppercase;
			}

			.notice.themeisle-sale {
				margin-top: 40px;
			}
		</style>
		<?php
	}

	/**
	 * Register Admin Page
	 *
	 * @since   1.7.1
	 * @access  public
	 */
	public function menu_callback() {
		echo '<div id="otter"></div>';
	}

	/**
	 * The content of the form submissions upsell page.
	 */
	public function form_submissions_callback() {
		?>
		<style>
			div.error, div.notice {
				display: none;
			}

			.otter-form-submissions-upsell-content {
				text-align: center;
				padding: 40px 20px;
				max-width: 520px;
				margin: 0 auto;
			}

			.otter-form-submissions-upsell-content h2 {
				font-size: 32px;
				margin-bottom: 25px;
			}

			.otter-form-submissions-upsell-content p {
				font-size: 14px;
				margin-bottom: 20px;
			}

			.otter-form-submissions-upsell-content .button {
				font-size: 16px;
				padding: 10px 50px;
				background-color: #ED6F57;
				border-color: #ED6F57;
			}

			.otter-form-submissions-upsell-content .button:hover {
				background-color: #E25C4F;
				border-color: #E25C4F;
			}
		</style>
		<div id="otter-form-submissions-upsell">
			<div class="otter-form-submissions-upsell-content">
				<img style="max-width: 100%" src="<?php echo esc_url( OTTER_BLOCKS_URL . 'assets/images/form-submissions-upsell.svg' ); ?>" alt="Otter Form Submissions Upsell" />
				<h2 style="line-height: 1"><?php esc_html_e( 'Collect Your Form Submissions', 'otter-blocks' ); ?></h2>
				<p><?php esc_html_e( 'Store, manage and analyze your form submissions with ease – all in one place. With Otter powerful features, managing submissions has never been simpler.', 'otter-blocks' ); ?></p>
				<a href="<?php echo esc_url( tsdk_translate_link( tsdk_utmify( 'https://themeisle.com/plugins/otter-blocks/upgrade/', 'form-submissions', 'admin' ) ) ); ?>" class="button button-primary" target="_blank"><?php esc_html_e( 'Explore Otter PRO', 'otter-blocks' ); ?></a>
			</div>
		</div>
		<?php
	}

	/**
	 * Load assets for option page.
	 *
	 * @since   1.7.1
	 * @access  public
	 */
	public function enqueue_options_assets() {
		$asset_file = include OTTER_BLOCKS_PATH . '/build/dashboard/index.asset.php';

		wp_enqueue_style(
			'otter-blocks-styles',
			OTTER_BLOCKS_URL . 'build/dashboard/style-index.css',
			array( 'wp-components' ),
			$asset_file['version']
		);

		wp_enqueue_script(
			'otter-blocks-scripts',
			OTTER_BLOCKS_URL . 'build/dashboard/index.js',
			array_merge( $asset_file['dependencies'], [ 'updates' ] ),
			$asset_file['version'],
			true
		);

		wp_set_script_translations( 'otter-blocks-scripts', 'otter-blocks' );

		wp_localize_script(
			'otter-blocks-scripts',
			'otterObj',
			$this->get_dashboard_data()
		);

		do_action( 'themeisle_internal_page', OTTER_PRODUCT_SLUG, 'dashboard' );
	}

	/**
	 * Get the dashboard data to store in global object.
	 *
	 * @return array
	 */
	public function get_dashboard_data() {
		$wp_upload_dir = wp_upload_dir( null, false );
		$basedir       = $wp_upload_dir['basedir'] . '/themeisle-gutenberg/';
		$offer         = new LimitedOffers();

		$global_data = array(
			'version'                => OTTER_BLOCKS_VERSION,
			'assetsPath'             => OTTER_BLOCKS_URL . 'assets/',
			'stylesExist'            => is_dir( $basedir ) || boolval( get_transient( 'otter_animations_parsed' ) ),
			'hasPro'                 => Pro::is_pro_installed(),
			'otterPage'              => tsdk_translate_link( tsdk_utmify( 'https://themeisle.com/plugins/otter-blocks/', 'welcome', 'admin' ) ),
			'upgradeLink'            => tsdk_translate_link( tsdk_utmify( Pro::get_url(), 'options', Pro::get_reference() ) ),
			'upgradeLinkFromTc'      => tsdk_utmify( Pro::get_url(), 'templatecloud' ),
			'tcUpgradeLink'          => tsdk_utmify( 'https://themeisle.com/plugins/templates-cloud/', 'templatecloud', 'otter-blocks' ),
			'tcDocs'                 => 'https://docs.themeisle.com/article/2191-templates-cloud-collections',
			'docsLink'               => Pro::get_docs_url(),
			'newPageUrl'             => esc_url( admin_url( 'post-new.php?post_type=page' ) ),
			'showFeedbackNotice'     => $this->should_show_feedback_notice(),
			'deal'                   => ! Pro::is_pro_installed() ? $offer->get_localized_data() : array(),
			'hasOnboarding'          => false !== get_theme_support( FSE_Onboarding::SUPPORT_KEY ),
			'days_since_install'     => intval( ( time() - get_option( 'otter_blocks_install', time() ) ) / DAY_IN_SECONDS ),
			'rootUrl'                => get_site_url(),
			'neveThemePreviewUrl'    => esc_url(
				add_query_arg(
					array(
						'theme' => 'neve',
					),
					admin_url( 'theme-install.php' )
				)
			),
			'neveThemeActivationUrl' => esc_url(
				add_query_arg(
					array(
						'action'     => 'activate',
						'stylesheet' => 'neve',
						'_wpnonce'   => wp_create_nonce( 'switch-theme_neve' ),
					),
					admin_url( 'themes.php' )
				)
			),
			'neveDashboardUrl'       => esc_url(
				add_query_arg(
					array(
						'page' => 'neve-welcome',
					),
					admin_url( 'admin.php' )
				)
			),
			'neveInstalled'          => defined( 'NEVE_VERSION' ),
			'hasPatternSources'      => Template_Cloud::has_used_pattern_sources(),
		);

		$global_data = apply_filters( 'otter_dashboard_data', $global_data );
		
		if (
			isset( $global_data['license'], $global_data['license']['key'] )
			&& 'free' !== $global_data['license']['key']
			&& 6 <= strlen( $global_data['license']['key'] )
		) {
			$global_data['license']['key'] = str_repeat( '*', 26 ) . substr( $global_data['license']['key'], -6 );
		}

		return $global_data;
	}

	/**
	 * Maybe redirect to dashboard page.
	 *
	 * @since   1.7.1
	 * @access  public
	 */
	public function maybe_redirect() {
		if ( ! get_option( 'themeisle_blocks_settings_redirect' ) ) {
			return;
		}

		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
			return;
		}

		if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) { // phpcs:ignore WordPress.VIP.SuperGlobalInputUsage.AccessDetected,WordPress.Security.NonceVerification.Recommended
			return;
		}

		update_option( 'themeisle_blocks_settings_redirect', false );
		wp_safe_redirect( admin_url( 'admin.php?page=otter&welcome=true' ) );
		exit;
	}

	/**
	 * Add elements for the survey.
	 *
	 * @return void
	 */
	public function survey_elements() {
		$screen = get_current_screen();

		if ( 'edit-otter_form_record' === $screen->id ) {
			do_action( 'themeisle_internal_page', OTTER_PRODUCT_SLUG, 'form-submissions' );
		}
	}

	/**
	 * Add elements for Form Block submission page.
	 *
	 * @return void
	 */
	public function form_submission_elements() {
		$screen = get_current_screen();

		if ( 'edit-otter_form_record' === $screen->id || 'otter-blocks_page_form-submissions-free' === $screen->id ) {
			$this->the_otter_banner();
		}
	}

	/**
	 * Whether to show the feedback notice or not.
	 *
	 * @return bool
	 */
	private function should_show_feedback_notice() {
		$installed = get_option( 'otter_blocks_install' );

		return ! empty( $installed ) && $installed < strtotime( '-5 days' );
	}

	/**
	 * The top Otter banner.
	 *
	 * @return void
	 */
	private function the_otter_banner() {
		?>
		<style>
			#screen-options-link-wrap {
				display: none;
			}

			.otter-banner {
				display: flex;
				background: #fff;
				padding: 10px 20px;
				margin-left: -20px
			}

			.otter-banner__content {
				display: flex;
				justify-content: space-between;
				flex-wrap: wrap;
				align-content: center;
				width: 100%;
				margin-left: 10px;
				align-items: center;
			}

			.otter-banner__version {
				align-self: center;
				font-size: 11px;
			}

			/* Hide the "Add New" button for Multisite WP. Second part is for Elementor */
			a.page-title-action:first-of-type, #e-admin-top-bar-root:not(.e-admin-top-bar--active)~#wpbody .wrap a.page-title-action:first-of-type {
				display: none;
			}

			#export-submissions {
				font-size: 14px;
				max-height: 35px;
			}
		</style>
		<div class="otter-banner">
			<div class="otter-banner__image">
				<img src="<?php echo esc_url( OTTER_BLOCKS_URL . 'assets/images/logo-alt.png' ); ?>" alt="<?php esc_attr_e( 'Otter Blocks', 'otter-blocks' ); ?>" style="width: 90px">
			</div>
			<div class="otter-banner__content">
				<h1 class="otter-banner__title" style="line-height: normal;"><?php esc_html_e( 'Form Submissions', 'otter-blocks' ); ?></h1>

				<?php if ( Pro::is_pro_active() ) : ?>
				<button id="export-submissions" class="button">
					<?php esc_html_e( 'Export', 'otter-blocks' ); ?>
				</button>
				<?php endif; ?>
			</div>
		</div>
		<script>
			window.document.addEventListener('DOMContentLoaded', () => {
				document.querySelector('#export-submissions')?.addEventListener('click', () => {
					fetch('<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>', {
						method: 'POST',
						headers: {
							'Content-Type': 'application/x-www-form-urlencoded'
						},
						body: new URLSearchParams({
							action: 'otter_form_submissions',
							_nonce: '<?php echo esc_attr( wp_create_nonce( 'otter_form_export_submissions' ) ); ?>'
						})
					})
						.then(response => response.text())
						.then(response => {
							const currentDate = new Date();
							const year = currentDate.getFullYear();
							const month = String(currentDate.getMonth() + 1).padStart(2, '0');
							const day = String(currentDate.getDate()).padStart(2, '0');

							const blob = new Blob([response], {type: 'text/xml'});
							const url = window.URL.createObjectURL(blob);
							const a = document.createElement('a');
							a.href = url;
							a.download = `otter_form_submissions__${year}-${month}-${day}.xml`;
							document.body.appendChild(a);
							a.click();
						})
						.catch(error => console.error('Error:', error));
				});

			})
		</script>
		<?php
	}

	/**
	 * Hook the form submissions widget.
	 *
	 * @return void
	 */
	public function form_submissions_widget() {
		wp_add_dashboard_widget(
			'otter_form_submissions_widget',
			__( 'Otter Blocks - Form Submissions', 'otter-blocks' ),
			array( $this, 'form_submissions_widget_content' )
		);
	}

	/**
	 * Display the form submissions widget content.
	 *
	 * @return void
	 */
	public function form_submissions_widget_content() {

		$is_active    = Pro::is_pro_active();
		$entries      = array();
		$count        = 0;
		$posts_filter = 'all';

		if ( $is_active ) {
			$posts_filter = isset( $_GET['otter_nonce'] ) && wp_verify_nonce( sanitize_key( $_GET['otter_nonce'] ), 'otter_widget_nonce' ) && isset( $_GET['otter_form_widget_filter'] ) ? sanitize_key( $_GET['otter_form_widget_filter'] ) : 'all';

			$query_args = array(
				'post_type'      => 'otter_form_record',
				'posts_per_page' => 5,
			);

			if ( 'all' !== $posts_filter ) {
				$query_args['post_status'] = $posts_filter;
			}

			$query = new \WP_Query( $query_args );


			$records_count = wp_count_posts( 'otter_form_record' );

			$count = $records_count->read + $records_count->unread;

			if ( 'read' === $posts_filter ) {
				$count = $records_count->read;
			} elseif ( 'unread' === $posts_filter ) {
				$count = $records_count->unread;
			}

			if ( $query->have_posts() ) {

				while ( $query->have_posts() ) {
					$query->the_post();

					$meta = get_post_meta( get_the_ID(), 'otter_form_record_meta', true );

					$title = null;
					$date  = null;

					if ( isset( $meta['post_id']['value'] ) ) {
						$date = get_the_date( 'F j, H:i', $meta['post_id']['value'] );
					}

					if ( isset( $meta['inputs'] ) && is_array( $meta['inputs'] ) ) {
						// Find the first email field and use that as the title.
						foreach ( $meta['inputs'] as $input ) {
							if ( isset( $input['type'] ) && 'email' === $input['type'] && ! empty( $input['value'] ) ) {
								$title = $input['value'];
								break;
							}
						}
					}


					if ( ! $title ) {

						if ( isset( $meta['post_id']['value'] ) ) {
							$title = __( 'Submission', 'otter-blocks' ) . ' #' . get_the_ID();
						} else {
							$title = __( 'No title', 'otter-blocks' );
						}
					}

					$entries[] = array(
						'title' => $title,
						'date'  => $date,
					);
				}
			}
		}

		?>
		<style>
			.o-upsell-container {
				display: flex;
				justify-content: center;
				align-items: center;
				width: 100%;
				margin-bottom: 8px;
			}

			.o-upsell-banner {
				display: flex;
				flex-direction: column;
				justify-content: center;
				align-items: center;
				padding: 24px;
				gap: 12px;
				isolation: isolate;

				width: fit-content;

				background: #FFFFFF;
				box-shadow: 0px 2px 25px 10px rgba(0, 0, 0, 0.08);
				border-radius: 6px;

				/* Inside auto layout */

				flex: none;
				order: 0;
				align-self: stretch;
				flex-grow: 0;

			}

			.o-upsell-banner .o-banner-tile {
				font-weight: 600;
				font-size: 16px;
				line-height: 150%;
				text-align: center;
			}

			.o-upsell-banner p {
				font-weight: 400;
				font-size: 13px;
				line-height: 150%;
				display: flex;
				align-items: center;
				text-align: center;
				margin: 0px;
			}

			.o-upsell-banner a {
				display: flex;
				flex-direction: row;
				justify-content: center;
				align-items: center;
				padding: 13.5px 24px;
				background: #ED6F57;
				border-radius: 2px;
				font-style: normal;
				font-weight: 600;
				font-size: 13px;
				line-height: 13px;
				color: #FFFFFF;
			}

			.o-upsell-banner img {
				width: 80px
			}

			.otter-form-submissions-widget {
				padding: 6px 3px 0px 3px;
			}

			.otter-form-submissions-widget a {
				text-decoration: none;
				text-align: center;
			}

			.otter-form-submissions-widget, .o-form-entries, .o-entries-list {
				display: flex;
				flex-direction: column;
			}

			.o-form-entries {
				gap: 12px;
			}

			.o-entries-header, .o-entry {
				display: flex;
				flex-direction: row;
				justify-content: space-between;
				align-items: center;
				font-size: 14px;
			}


			.o-entries-header .o-title {
				font-size: 14px;
				font-weight: 600;
			}

			.o-entries-list {
				gap: 5px;
				font-size: 13px;
			}

			.o-entry.header {
				font-size: 14px;
				font-weight: bold;
			}

			.o-entry:not(:last-child) {
				padding-bottom: 6px;
				border-bottom: 1px solid #eee;
			}

			.o-submissions-view {
				width: 100%;
				display: flex;
				align-items: center;
				justify-content: center;
				padding-top: 10px;
			}

			.otter-form-submissions-widget.inactive .o-form-entries {
				color: #CCC;
			}

		</style>
		<?php if ( $is_active ) { ?>
			<script>
				window.document.addEventListener('DOMContentLoaded', () => {
					const select = document.querySelector('#otter_form_submissions_widget #otter-form-submissions-widget__form-select');
					const entriesContainer = document.querySelector('#otter_form_submissions_widget .o-entries-list');

					if (select && entriesContainer) {
						select.addEventListener('change', (e) => {
							const value = e.target.value;

							// change the url param based on the value
							const url = new URL(window.location.href);
							url.searchParams.set('otter_form_widget_filter', value);
							url.searchParams.set('otter_nonce', '<?php echo esc_attr( wp_create_nonce( 'otter_widget_nonce' ) ); ?>')
							url.hash = '#otter_form_submissions_widget';

							window.location.href = url.href;
						})
					}
				})
			</script>
		<?php } ?>
		<div class="otter-form-submissions-widget <?php echo ! $is_active ? 'inactive' : ''; ?>">

			<?php if ( ! $is_active ) { ?>
				<div class="o-upsell-container">
					<div class="o-upsell-banner">
						<img src="<?php echo esc_url_raw( OTTER_BLOCKS_URL . 'assets/images/logo-alt.png' ); ?>" alt="Otter Logo" />
						<div class="o-banner-tile">
							<?php esc_html_e( 'Collect your Form Submissions with Otter Blocks', 'otter-blocks' ); ?>
						</div>
						<p><?php esc_html_e( 'With Otter\'s powerful features, you can easily store and manage form submissions - all in one place.', 'otter-blocks' ); ?></p>
						<a target="_blank" href="<?php echo esc_url( Pro::get_url() ); ?>" ><?php esc_html_e( 'Upgrade to Otter Pro', 'otter-blocks' ); ?></a>
					</div>
				</div>
			<?php } ?>

			<div class="o-form-entries">
				<div class="o-entries-header">
					<div class="o-title">
						<?php if ( 0 === count( $entries ) || ! $is_active ) { ?>
							<?php esc_html_e( 'Total Entries', 'otter-blocks' ); ?>
						<?php } else { ?>
							<?php esc_html_e( 'Total Entries', 'otter-blocks' ); ?>:
							<span class="otter-form-submissions-widget__total-entries">
							<?php echo esc_html( strval( $count ) ); ?>
						</span>
						<?php } ?>
					</div>

					<select name="otter-form-submissions-widget__form-select" id="otter-form-submissions-widget__form-select" class="o-entries-filter" <?php echo ! $is_active ? 'disabled' : ''; ?> >
						<option value="all" <?php echo 'all' === $posts_filter ? 'selected' : ''; ?> ><?php esc_html_e( 'All', 'otter-blocks' ); ?></option>
						<option value="read" <?php echo 'read' === $posts_filter ? 'selected' : ''; ?>><?php esc_html_e( 'Read', 'otter-blocks' ); ?></option>
						<option value="unread" <?php echo 'unread' === $posts_filter ? 'selected' : ''; ?>><?php esc_html_e( 'Unread', 'otter-blocks' ); ?></option>
					</select>
				</div>
				<div class="o-entries-list">
					<?php if ( 0 === count( $entries ) || ! $is_active ) { ?>
						<div class="o-no-entries">
							<?php esc_html_e( 'Your submission will appear here.', 'otter-blocks' ); ?>
						</div>
					<?php } else { ?>
						<div class="o-entry header">
							<div class="o-entry__title">
								<?php esc_html_e( 'Submission', 'otter-blocks' ); ?>
							</div>
							<div class="o-entry__date">
								<?php esc_html_e( 'Date', 'otter-blocks' ); ?>
							</div>
						</div>
						<?php foreach ( $entries as $entry ) { ?>
							<div class="o-entry">
								<div class="o-entry__title">
									<?php echo esc_html( $entry['title'] ); ?>
								</div>
								<div class="o-entry__date">
									<?php echo esc_html( $entry['date'] ); ?>

								</div>
							</div>
						<?php } ?>
						<div class="o-submissions-view">
							<a href="<?php echo esc_url( admin_url( 'edit.php?post_type=otter_form_record' ) ); ?>" ><?php esc_html_e( 'Manage all Submissions', 'otter-blocks' ); ?></a>
						</div>
					<?php } ?>
				</div>
			</div>


		</div>
		<?php
	}

	/**
	 * Register survey.
	 * 
	 * @param array  $data The data in Formbricks format.
	 * @param string $page_slug The page slug.
	 * 
	 * @return array The data in Frombricks format.
	 */
	public static function get_survey_metadata( $data, $page_slug ) {
		$dash_data           = apply_filters( 'otter_dashboard_data', array() );
		$install_days_number = intval( ( time() - get_option( 'otter_blocks_install', time() ) ) / DAY_IN_SECONDS );

		$data = array(
			'environmentId' => 'clp9hqm8c1osfdl2ixwd0k0iz',
			'attributes'    => array(
				'install_days_number' => $install_days_number,
				'plan'                => isset( $dash_data['license'], $dash_data['license']['type'] ) ? $dash_data['license']['type'] : 'free',
				'freeVersion'         => OTTER_BLOCKS_VERSION,
			),
		);

		if ( isset( $dash_data['license'], $dash_data['license']['key'] ) ) {
			$data['attributes']['license_key'] = apply_filters( 'themeisle_sdk_secret_masking', apply_filters( 'product_otter_license_key', '' ) );
		}

		if ( isset( $dash_data['proVersion'] ) ) {
			$data['attributes']['proVersion'] = $dash_data['proVersion'];
		}

		return $data;
	}

	/**
	 * The instance method for the static class.
	 * Defines and returns the instance of the static class.
	 *
	 * @static
	 * @since 1.7.1
	 * @access public
	 * @return Dashboard
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
			self::$instance->init();
		}

		return self::$instance;
	}

	/**
	 * Throw error on object clone
	 *
	 * The whole idea of the singleton design pattern is that there is a single
	 * object therefore, we don't want the object to be cloned.
	 *
	 * @access public
	 * @since 1.7.1
	 * @return void
	 */
	public function __clone() {
		// Cloning instances of the class is forbidden.
		_doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'otter-blocks' ), '1.0.0' );
	}

	/**
	 * Disable unserializing of the class
	 *
	 * @access public
	 * @since 1.7.1
	 * @return void
	 */
	public function __wakeup() {
		// Unserializing instances of the class is forbidden.
		_doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'otter-blocks' ), '1.0.0' );
	}
}
