<?php
/**
 * Disable Thumbnail Generation Module
 *
 * @package DisableThumbnailGeneration
 * @since 1.0.0
 */

namespace DisableThumbnailGeneration;

use WP_PowerSuite\Core\AbstractModule;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Module extends AbstractModule {

	private const MODULE_ID      = 'disable-thumbnail-generation';
	private const MODULE_VERSION = '1.0.0';

	/** @var array{disable_all: bool, disabled_sizes: array<int, string>}|null */
	private ?array $settings_cache = null;

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

	public function getName(): string {
		return __( 'Disable Thumbnail Generation', 'wp-powersuite' );
	}

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

	public function getDescription(): string {
		return __( 'Prevents WordPress from automatically creating multiple image sizes when you upload images. Saves disk space and speeds up uploads. Existing images keep their thumbnails, but new uploads only keep the original.', 'wp-powersuite' );
	}

	public function getContext(): string|array {
		return [ 'admin', 'rest', 'ajax', 'cron' ];
	}

	protected function registerHooks(): void {
		$settings = $this->getSettings();
		if ( ! $settings['disable_all'] && $settings['disabled_sizes'] === [] ) {
			return;
		}

		add_filter( 'intermediate_image_sizes_advanced', [ $this, 'filterImageSizes' ], 10, 3 );
	}

	/**
	 * @param array<int|string, array{width?: int, height?: int, crop?: bool}> $sizes
	 * @param array<string, mixed>                                             $metadata
	 * @param int                                                              $attachment_id
	 * @return array<int|string, array{width?: int, height?: int, crop?: bool}>
	 */
	public function filterImageSizes( $sizes, $metadata, $attachment_id ): array {
		if ( ! is_array( $sizes ) ) {
			return [];
		}

		$settings = $this->getSettings();
		if ( $settings['disable_all'] ) {
			return [];
		}

		$disabled = $settings['disabled_sizes'];
		if ( $disabled === [] ) {
			return $sizes;
		}

		foreach ( $disabled as $size_name ) {
			unset( $sizes[ $size_name ] );
		}

		return $sizes;
	}

	/**
	 * @return array<int, array{name: string, width: int, height: int, crop: bool}>
	 */
	public static function getRegisteredImageSizes(): array {
		static $cached = null;
		if ( is_array( $cached ) ) {
			return $cached;
		}

		global $_wp_additional_image_sizes;

		$sizes   = [];
		$default = [ 'thumbnail', 'medium', 'medium_large', 'large' ];

		foreach ( $default as $name ) {
			$sizes[] = [
				'name'   => $name,
				'width'  => (int) get_option( "{$name}_size_w", 0 ),
				'height' => (int) get_option( "{$name}_size_h", 0 ),
				'crop'   => (bool) get_option( "{$name}_crop", false ),
			];
		}

		if ( is_array( $_wp_additional_image_sizes ) ) {
			foreach ( $_wp_additional_image_sizes as $name => $data ) {
				$sizes[] = [
					'name'   => (string) $name,
					'width'  => (int) ( $data['width'] ?? 0 ),
					'height' => (int) ( $data['height'] ?? 0 ),
					'crop'   => (bool) ( $data['crop'] ?? false ),
				];
			}
		}

		$cached = $sizes;

		return $cached;
	}

	/**
	 * @param array<string, mixed> $raw
	 * @return array{disable_all: bool, disabled_sizes: array<int, string>}
	 */
	public static function normalizeSettings( array $raw ): array {
		$disabled = isset( $raw['disabled_sizes'] ) && is_array( $raw['disabled_sizes'] )
			? array_values(
				array_filter(
					$raw['disabled_sizes'],
					static fn( $name ): bool => is_string( $name ) && $name !== ''
				)
			)
			: [];

		return [
			'disable_all'    => isset( $raw['disable_all'] ) && (string) $raw['disable_all'] === '1',
			'disabled_sizes' => $disabled,
		];
	}

	/**
	 * @return array{disable_all: bool, disabled_sizes: array<int, string>}
	 */
	private function getSettings(): array {
		if ( $this->settings_cache !== null ) {
			return $this->settings_cache;
		}

		$raw = $this->moduleSettings()->all( [] );
		$this->settings_cache = self::normalizeSettings( is_array( $raw ) ? $raw : [] );

		return $this->settings_cache;
	}
}
