<?php
namespace DisablePostAutosave;

use WP_PowerSuite\Core\AbstractModule;

class Module extends AbstractModule {

	private const MODULE_ID = 'disable-post-autosave';
	private const MODULE_VERSION = '1.2.1';

	/** Effectively disables autosave (1 year) for classic and block editors. */
	private const DISABLED_AUTOSAVE_INTERVAL = YEAR_IN_SECONDS;

	public function getId(): string {
		return self::MODULE_ID;
	}

	public function getName(): string {
		return __( 'Disable Post Auto-Save', 'wp-powersuite' );
	}

	public function getVersion(): string {
		return self::MODULE_VERSION;
	}

	public function getDescription(): string {
		return __( 'Fewer automatic saves while you edit, so your site stores fewer hidden draft revisions and stays tidier.', 'wp-powersuite' );
	}

	public function getContext(): array {
		return [ 'admin' ];
	}

	protected function registerHooks(): void {
		add_action( 'admin_enqueue_scripts', [ $this, 'removeAutosaveScript' ], 999 );
		add_filter( 'wp_autosave_interval', [ $this, 'disableAutosaveInterval' ], 999 );
		add_filter( 'block_editor_settings_all', [ $this, 'disableBlockEditorAutosave' ], 99, 2 );
	}

	public function disableAutosaveInterval( int $interval ): int {
		if ( ! $this->autosaveAppliesToCurrentScreen() ) {
			return $interval;
		}

		return self::DISABLED_AUTOSAVE_INTERVAL;
	}

	/**
	 * @param array<string, mixed> $settings Block editor settings.
	 * @param \WP_Block_Editor_Context $block_editor_context Editor context.
	 * @return array<string, mixed>
	 */
	public function disableBlockEditorAutosave( array $settings, \WP_Block_Editor_Context $block_editor_context ): array {
		if ( ! $this->autosaveAppliesToEditorContext( $block_editor_context ) ) {
			return $settings;
		}

		$settings['autosaveInterval'] = self::DISABLED_AUTOSAVE_INTERVAL;

		return $settings;
	}

	public function removeAutosaveScript(): void {
		if ( ! $this->autosaveAppliesToCurrentScreen() ) {
			return;
		}

		wp_deregister_script( 'autosave' );
	}

	/**
	 * `apply_filters( 'wp_powersuite_disable_post_autosave_post_types', null )`:
	 * null = all post types; string[] = only those types.
	 *
	 * @return array<string>|null
	 */
	private function getAutosaveTargetPostTypes(): ?array {
		$types = apply_filters( 'wp_powersuite_disable_post_autosave_post_types', null );
		if ( $types === null ) {
			return null;
		}
		if ( ! is_array( $types ) ) {
			return null;
		}
		$types = array_values( array_filter( array_map( 'sanitize_key', $types ) ) );

		return $types === [] ? null : $types;
	}

	private function autosaveAppliesToCurrentScreen(): bool {
		if ( ! $this->isPostEditorScreen() ) {
			return false;
		}

		$limited = $this->getAutosaveTargetPostTypes();
		if ( $limited === null ) {
			return true;
		}

		if ( ! function_exists( 'get_current_screen' ) ) {
			return false;
		}

		$screen = get_current_screen();
		if ( ! $screen || empty( $screen->post_type ) ) {
			return false;
		}

		return in_array( $screen->post_type, $limited, true );
	}

	private function autosaveAppliesToEditorContext( \WP_Block_Editor_Context $block_editor_context ): bool {
		$limited = $this->getAutosaveTargetPostTypes();
		if ( $limited === null ) {
			return true;
		}

		$post = $block_editor_context->post ?? null;
		if ( ! $post instanceof \WP_Post ) {
			return false;
		}

		return in_array( $post->post_type, $limited, true );
	}

	private function isPostEditorScreen(): bool {
		global $pagenow;

		if ( in_array( $pagenow, [ 'post.php', 'post-new.php' ], true ) ) {
			return true;
		}

		if ( ! function_exists( 'get_current_screen' ) ) {
			return false;
		}

		$screen = get_current_screen();
		if ( $screen && in_array( $screen->base, [ 'post', 'page' ], true ) ) {
			return true;
		}

		return false;
	}
}
