<?php

class WP_Site_Icon_Admin_UI {
	/**
	 * The size to which to crop the image so that we can display it in the UI nicely.
	 *
	 * @since 4.3.0
	 *
	 * @var int
	 *
	 * TO DO: Rename
	 */
	public $page_crop = 512;

	var $admin_ui_processing;
	var $site_icon;
	var $admin_page_hook;

	public function __construct( $admin_ui_processing, $site_icon ) {
		$this->admin_ui_processing = $admin_ui_processing;
		$this->site_icon = $site_icon;

		// Add the favicon to the backend.
		add_action( 'admin_head', 'wp_site_icon' );

		add_action( 'admin_menu', array( $this, 'add_site_icon_page_to_menu' ) );
		add_action( 'admin_init', array( $this, 'add_upload_page_settings' ) );

		add_action( 'admin_action_set_site_icon',    array( $this, 'set_site_icon'    ) );
		add_action( 'admin_action_remove_site_icon', array( $this, 'remove_site_icon' ) );
	}

	// To Do: nonce checking
	public function site_icon_page_controller() {
		$action = isset( $_GET['action'] ) ? $_GET['action'] : 'select-site-icon';

		switch ( $action ) {
			case 'select-site-icon':
				$this->display_upload_page();
				break;

			case 'crop-site-icon':
				// Handle image upload for the no Javascript version.
				if ( isset ( $_GET['upload'] ) ) {
					$attachment_id = $this->admin_ui_processing->upload_site_icon_image();
				} else {
					// The Javascript upload skips the select and upload steps, providing the attachment ID.
					$attachment_id = $_GET['file'];
				}

				// Verify that the image is large enough.
				$image_size = $this->admin_ui_processing->get_image_size_from_attachment( $attachment_id );

				// TO DO: Move this to a method.
				if ( $image_size[0] < $this->site_icon->min_size ) {
					add_settings_error( 'site-icon', 'too-small', sprintf( __( 'The selected image is smaller than %upx in width.' ), $this->site_icon->min_size ) );
					$this->display_upload_page();
				} elseif ( $image_size[1] < $this->site_icon->min_size ) {
					add_settings_error( 'site-icon', 'too-small', sprintf( __( 'The selected image is smaller than %upx in height.' ), $this->site_icon->min_size ) );
					$this->display_upload_page();
				} else {
					// TO DO: Move this to a method.
					// URL of the uploaded image.
					$image_url = $this->admin_ui_processing->get_site_icon_image_url( $attachment_id );
					// Dimensions of the uploaded image adapted to the admin.
					$max_height = $this->admin_ui_processing->calculate_height_of_image_for_cropping( $attachment_id, $this->page_crop );
					// Add the default crop values for the no JS version.
					$default_crop = $this->admin_ui_processing->calculate_default_values_for_crop( $this->page_crop, $max_height );
					// Ratio for cropping
					$crop_ratio = $image_size[0] / $this->page_crop;

					$this->display_crop_page( $attachment_id, $image_url, $this->page_crop, $max_height, $default_crop, $crop_ratio );
				}
				break;

			default:
				wp_safe_redirect( admin_url( 'options-general.php#site-icon' ) );
				exit;
		}
	}

	/**
	 * Adds the Site Icon Page to the admin menu.
	 *
	 * The `parent_slug` argument in `add_menu_page()` is set to `null`, so that no link is added in the admin interface.
	 *
	 * @since 4.3.0
	 */
	public function add_site_icon_page_to_menu() {
		$hook = add_submenu_page( null, __( 'Site Icon' ), __( 'Site Icon' ), 'manage_options', 'site-icon', array( $this, 'site_icon_page_controller' ) );

		add_action( "admin_print_scripts-$hook", array( $this, 'enqueue_scripts' ) );
	}

	/**
	 * Register a settings section for uploading a Site Icon image.
	 *
	 * @since 4.3.0
	 */
	public function add_upload_page_settings() {
		add_settings_section( 'site-icon-upload', false, false, 'site-icon-upload' );
		add_settings_field( 'site-icon-upload', __( 'Upload Image' ), array( $this, 'display_upload_page_image_selection' ), 'site-icon-upload', 'site-icon-upload', array(
			'label_for' => 'site-icon-upload',
		) );
	}

	/**
	 * Add scripts to admin settings pages.
	 *
	 * @since 4.3.0
	 */
	public function enqueue_scripts() {
		wp_enqueue_style( 'jcrop' );
		wp_enqueue_script( 'site-icon-crop' );
	}

	/**
	 * Display the admin page for uploading a Site Icon image.
	 *
	 * This screen is only visible when Javascript is deactivated.
	 *
	 * @since 4.3.0
	 */
	public function display_upload_page() {
		?>
		<div class="wrap">
			<h2><?php _e( 'Add Site Icon' ); ?></h2>
			<?php settings_errors( 'site-icon' ); ?>
			<?php do_settings_sections( 'site-icon-upload' ); ?>
		</div>
	<?php
	}

	/**
	 * Settings field for file upload.
	 *
	 * @since 4.3.0
	 */
	public function display_upload_page_image_selection() {
		// Render modal for uploading via Javascript.
		// TO DO: Script enqueuing should be done in a single method.
		wp_enqueue_media();
		wp_enqueue_script( 'site-icon' );
		wp_dequeue_script( 'site-icon-crop' );

		$update_url = esc_url( add_query_arg( array(
			'page' => 'site-icon',
			'action' => 'crop-site-icon',
		), wp_nonce_url( admin_url( 'options-general.php' ), 'crop-site-icon' ) ) );
		?>
		<p class="hide-if-no-js">
			<label class="screen-reader-text" for="choose-from-library-link"><?php _e( 'Choose an image from your media library:' ); ?></label>
			<?php
				printf( '<button type="button" id="choose-from-library-link" class="button" data-update-link="%$1s" data-choose="%$2s" data-update="%$3s">%$4s</button>',
					esc_attr( $update_url ),
					esc_attr__( 'Choose a Site Icon' ),
					esc_attr__( 'Set as Site Icon' ),
					__( 'Choose Image' )
				);
			?>
		</p>

		<?php // Upload form for when Javascript is deactivated ?>
		<form class="hide-if-js" action="<?php echo esc_url( admin_url( 'options-general.php?page=site-icon&action=crop-site-icon&upload' ) ); ?>" method="post" enctype="multipart/form-data">
			<input name="action" value="crop_site_icon" type="hidden" />
			<input name="site-icon" type="file" />
			<input name="submit" value="<?php esc_attr_e( 'Upload Image' ); ?>" type="submit" class="button button-primary" />
			<p class="description">
				<?php printf( __( 'The image is recommended to be a square image of at least %spx in both width and height.' ), "<strong>" . absint( $this->site_icon->min_size ) . '</strong>' ); ?>
			</p>
			<?php wp_nonce_field( 'crop-site-icon' ); ?>
		</form>
	<?php
	}

	public function display_crop_page( $attachment_id, $image_url, $resized_image_width, $resized_image_height, $default_crop, $crop_ratio ) {
		check_admin_referer( 'crop-site-icon' );

		// TO DO: Script enqueuing should be done in a single method.
		$image_size = $this->admin_ui_processing->get_attachment_image_size( $attachment_id );
		wp_localize_script( 'site-icon-crop', 'wpSiteIconCropData', $this->admin_ui_processing->calculate_default_values_for_javascript_cropper( $crop_ratio, $this->page_crop, $resized_image_width, $resized_image_height, $image_size[0], $image_size[1] ) );
	?>
		<div class="wrap">
			<h2 class="site-icon-title"><?php _e( 'Site Icon' ); ?></h2>
			<?php settings_errors( 'site-icon' ); ?>

			<div class="site-icon-crop-shell">
				<form action="options-general.php" method="post" enctype="multipart/form-data">
					<p class="hide-if-no-js description"><?php _e('Choose the part of the image you want to use as your site icon.'); ?></p>
					<p class="hide-if-js description"><strong><?php _e( 'You need Javascript to choose a part of the image.'); ?></strong></p>
					<?php
						// Image which is used to select the right cropping.
						// This image needs to be resized to allow for easy cropping.
						printf( '<img src="%1$s" id="crop-image" class="site-icon-crop-image" width="%2$s" height="%3$s" alt="%4$s" />',
							esc_url( $image_url ),
							absint( $resized_image_width ),
							absint( $resized_image_height ),
							esc_attr__( 'Image to be cropped' )
						);

						// Site icon preview in browser bar and on mobile.
					?>
					<div class="site-icon-crop-preview-shell hide-if-no-js">
						<h3><?php _e( 'Preview' ); ?></h3>
						<strong><?php _e( 'As your favicon' ); ?></strong>
						<div class="site-icon-crop-favicon-preview-shell">
							<img src="images/browser.png" class="site-icon-browser-preview" width="182" height="" alt="<?php esc_attr_e( 'Browser Chrome' ); ?>"/>
							<div class="site-icon-crop-preview-favicon">
								<img src="<?php echo esc_url( $image_url ); ?>" id="preview-favicon" alt="<?php esc_attr_e( 'Preview Favicon' ); ?>"/>
							</div>
							<span class="site-icon-browser-title"><?php bloginfo( 'name' ); ?></span>
						</div>
						<strong><?php _e( 'As a mobile icon' ); ?></strong>
						<div class="site-icon-crop-preview-homeicon">
							<img src="<?php echo esc_url( $image_url ); ?>" id="preview-homeicon" alt="<?php esc_attr_e( 'Preview Home Icon' ); ?>"/>
						</div>
					</div>

					<?php // Default crop values for no JS fallback. ?>
					<input type="hidden" id="crop-x" name="crop-x" value="<?php echo absint( $default_crop['crop_x'] ); ?>" />
					<input type="hidden" id="crop-y" name="crop-y" value="<?php echo absint( $default_crop['crop_y'] ); ?>" />
					<input type="hidden" id="crop-width" name="crop-w" value="<?php echo absint( $default_crop['crop_size'] ); ?>" />
					<input type="hidden" id="crop-height" name="crop-h" value="<?php echo absint( $default_crop['crop_size'] ); ?>" />

					<input type="hidden" name="action" value="set_site_icon" />
					<input type="hidden" name="attachment_id" value="<?php echo esc_attr( $attachment_id ); ?>" />

					<input type="hidden" name="crop_ratio" value="<?php echo esc_attr( $crop_ratio ); ?>" />
					<?php if ( empty( $_POST ) && isset( $_GET['file'] ) ) : ?>
						<input type="hidden" name="create-new-attachment" value="true" />
					<?php endif; ?>
					<?php wp_nonce_field( 'set-site-icon' ); ?>

					<p class="submit">
						<?php submit_button( __( 'Crop and Publish' ), 'primary hide-if-no-js', 'submit', false ); ?>
						<?php submit_button( __( 'Publish' ), 'primary hide-if-js', 'submit', false ); ?>
						<a class="button secondary" href="options-general.php"><?php _e( 'Cancel' ); ?></a>
					</p>
				</form>
			</div>
		</div>
	<?php
	}

	/**
	 * Saves a new Site Icon.
	 *
	 * TO DO: Split this apart, and move code to smaller methods in `WP_Site_Icon_Admin_Processing`.
	 *
	 * @since 4.3.0
	 */
	public function set_site_icon() {
		check_admin_referer( 'set-site-icon' );

		// Delete any existing site icon images.
		$this->admin_ui_processing->delete_site_icon();

		$attachment_id = absint( $_POST['attachment_id'] );

		// TODO
		if ( empty( $_POST['skip-cropping'] ) ) {
			$crop_ratio = (float) $_POST['crop_ratio'];
			$crop_data = $this->admin_ui_processing->convert_coordinates_from_resized_to_full( $_POST['crop-x'], $_POST['crop-y'], $_POST['crop-w'], $_POST['crop-h'], $crop_ratio );
			$cropped = wp_crop_image( $attachment_id, $crop_data['crop_x'], $crop_data['crop_y'], $crop_data['crop_width'], $crop_data['crop_height'], $this->site_icon->min_size, $this->site_icon->min_size );
		} elseif ( ! empty( $_POST['create-new-attachment'] ) ) {
			$cropped = _copy_image_file( $attachment_id );
		} else {
			$cropped = get_attached_file( $attachment_id );
		}

		if ( ! $cropped || is_wp_error( $cropped ) ) {
			wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
		}

		$object = $this->admin_ui_processing->create_attachment_object( $cropped, $attachment_id );

		if ( ! empty( $_POST['create-new-attachment'] ) ) {
			unset( $object['ID'] );
		}

		// Update the attachment
		add_filter( 'intermediate_image_sizes_advanced', array( $this->site_icon, 'additional_sizes' ) );
		$attachment_id = $this->admin_ui_processing->insert_attachment( $object, $cropped );
		remove_filter( 'intermediate_image_sizes_advanced', array( $this->site_icon, 'additional_sizes' ) );

		// Save the site_icon data into option
		update_option( 'site_icon', $attachment_id );

		add_settings_error( 'site-icon', 'icon-updated', __( 'Site Icon updated.' ), 'updated' );
	}

	/**
	 * Removes site icon.
	 *
	 * @since 4.3.0
	 */
	public function remove_site_icon() {
		check_admin_referer( 'remove-site-icon' );

		// TO DO: Check return value to display success message.
		$this->admin_ui_processing->delete_site_icon();

		add_settings_error( 'site-icon', 'icon-removed', __( 'Site Icon removed.' ), 'updated' );
	}

}

$site_icon_admin = new WP_Site_Icon_Admin_UI( new WP_Site_Icon_Admin_Processing(), WP_Site_Icon::get_instance() );