<?php

class Meow_WR2X_Ajax {

	public $core = null;

	public function __construct( $core) {
		$this->core = $core;
		add_action( 'wp_ajax_wr2x_generate', array( $this, 'wp_ajax_wr2x_generate' ) );
		add_action( 'wp_ajax_wr2x_delete', array( $this, 'wp_ajax_wr2x_delete' ) );
		add_action( 'wp_ajax_wr2x_delete_full', array( $this, 'wp_ajax_wr2x_delete_full' ) );
		add_action( 'wp_ajax_wr2x_list_all', array( $this, 'wp_ajax_wr2x_list_all' ) );
		add_action( 'wp_ajax_wr2x_replace', array( $this, 'wp_ajax_wr2x_replace' ) );
		add_action( 'wp_ajax_wr2x_upload', array( $this, 'wp_ajax_wr2x_upload' ) );
		add_action( 'wp_ajax_wr2x_retina_details', array( $this, 'wp_ajax_wr2x_retina_details' ) );
		add_action( 'admin_head', array( $this, 'admin_head' ) );
	}

	function admin_head() {
		?>
		<script type="text/javascript" >

			/* GENERATE RETINA IMAGES ACTION */

			var current;
			var maxPhpSize = <?php echo $this->core->get_max_filesize(); ?>;
			var ids = [];
			var errors = 0;
			var ajax_action = "generate"; // generate | delete

			function wr2x_display_please_refresh() {
				wr2x_refresh_progress_status();
				jQuery('#wr2x_progression').html(jQuery('#wr2x_progression').html() + " - <?php echo _e( "<a href='?page=wp-retina-2x&view=issues&refresh=true'>Refresh</a> this page.", 'wp-retina-2x' ); ?>");
			}

			function wr2x_refresh_progress_status() {
				var errortext = "";
				if ( errors > 0 ) {
					errortext = ' - ' + errors + ' error(s)';
				}
				jQuery('#wr2x_progression').text(current + "/" + ids.length +
					" (" + Math.round(current / ids.length * 100) + "%)" + errortext);
			}

			function wr2x_do_next () {
				var data = { action: 'wr2x_' + ajax_action, attachmentId: ids[current - 1] };
				wr2x_refresh_progress_status();
				jQuery.post(ajaxurl, data, function (response) {
					try {
						reply = jQuery.parseJSON(response);
					}
					catch (e) {
						reply = null;
					}
					if ( !reply || !reply.success )
						errors++;
					else {
						wr2x_refresh_media_sizes(reply.results);
						if (reply.results_full)
							wr2x_refresh_full(reply.results_full);
					}
					if (++current <= ids.length)
						wr2x_do_next();
					else {
						current--;
						wr2x_display_please_refresh();
					}
				}).fail(function () {
					errors++;
					if (++current <= ids.length)
						wr2x_do_next();
					else {
						current--;
						wr2x_display_please_refresh();
					}
				});
			}

			function wr2x_do_all () {
				current = 1;
				ids = [];
				errors = 0;
				var data = { action: 'wr2x_list_all', issuesOnly: 0 };
				jQuery('#wr2x_progression').text("<?php _e( "Wait...", 'wp-retina-2x' ); ?>");
				jQuery.post(ajaxurl, data, function (response) {
					reply = jQuery.parseJSON(response);
					if (reply.success = false) {
						alert('Error: ' + reply.message);
						return;
					}
					if (reply.total == 0) {
						jQuery('#wr2x_progression').html("<?php _e( "Nothing to do ;)", 'wp-retina-2x' ); ?>");
						return;
					}
					ids = reply.ids;
					jQuery('#wr2x_progression').text(current + "/" + ids.length + " (" + Math.round(current / ids.length * 100) + "%)");
					wr2x_do_next();
				});
			}

			function wr2x_delete_all () {
				ajax_action = 'delete';
				wr2x_do_all();
			}

			function wr2x_generate_all () {
				ajax_action = 'generate';
				wr2x_do_all();
			}

			// Refresh the dashboard retina full with the results from the Ajax operation (Upload)
			function wr2x_refresh_full (results) {
				jQuery.each(results, function (id, html) {
					jQuery('#wr2x-info-full-' + id).html(html);
					jQuery('#wr2x-info-full-' + id + ' img').attr('src', jQuery('#wr2x-info-full-' + id + ' img').attr('src')+'?'+ Math.random());
					jQuery('#wr2x-info-full-' + id + ' img').on('click', function (evt) {
						wr2x_delete_full( jQuery(evt.target).parents('.wr2x-file-row').attr('postid') );
					});
				});
			}

			// Refresh the dashboard media sizes with the results from the Ajax operation (Replace or Generate)
			function wr2x_refresh_media_sizes (results) {
				jQuery.each(results, function (id, html) {
					jQuery('#wr2x-info-' + id).html(html);
				});
			}

			function wr2x_generate (attachmentId, retinaDashboard) {
				var data = { action: 'wr2x_generate', attachmentId: attachmentId };
				jQuery('#wr2x_generate_button_' + attachmentId).text("<?php echo __( "Wait...", 'wp-retina-2x' ); ?>");
				jQuery.post(ajaxurl, data, function (response) {
					var reply = jQuery.parseJSON(response);
					if (!reply.success) {
						alert(reply.message);
						return;
					}
					jQuery('#wr2x_generate_button_' + attachmentId).html("<?php echo __( "GENERATE", 'wp-retina-2x' ); ?>");
					wr2x_refresh_media_sizes(reply.results);
				});
			}

			/* REPLACE FUNCTION */

			function wr2x_stop_propagation(evt) {
				evt.stopPropagation();
				evt.preventDefault();
			}

			function wr2x_delete_full(attachmentId) {
				var data = {
					action: 'wr2x_delete_full',
					isAjax: true,
					attachmentId: attachmentId
				};

				jQuery.post(ajaxurl, data, function (response) {
					var data = jQuery.parseJSON(response);
					if (data.success === false) {
						alert(data.message);
					}
					else {
						wr2x_refresh_full(data.results);
						wr2x_display_please_refresh();
					}
				});
			}

			function wr2x_load_details(attachmentId) {
				var data = {
					action: 'wr2x_retina_details',
					isAjax: true,
					attachmentId: attachmentId
				};

				jQuery.post(ajaxurl, data, function (response) {
					var data = jQuery.parseJSON(response);
					if (data.success === false) {
						alert(data.message);
					}
					else {
						jQuery('#meow-modal-info .loading').css('display', 'none');
						jQuery('#meow-modal-info .content').html(data.result);
					}
				});
			}

			function wr2x_filedropped (evt) {
				wr2x_stop_propagation(evt);
				var files = evt.dataTransfer.files;
				var count = files.length;
				if (count < 0) {
					return;
				}

				var wr2x_replace = jQuery(evt.target).parent().hasClass('wr2x-fullsize-replace');
				var wr2x_upload = jQuery(evt.target).parent().hasClass('wr2x-fullsize-retina-upload');

				function wr2x_handleprogress(prg) {
					console.debug("Upload of " + prg.srcElement.filename + ": " + prg.loaded / prg.total * 100 + "%");
				}

				function wr2x_uploadFile(file, attachmentId, filename) {
					var action = "";
					if (wr2x_replace) {
						action = 'wr2x_replace';
					}
					else if (wr2x_upload) {
						action = 'wr2x_upload';
					}
					else {
						alert("Unknown command. Contact the developer.");
					}
					var data = new FormData();
	    		data.append('file', file);
					data.append('action', action);
					data.append('attachmentId', attachmentId);
					data.append('isAjax', true);
					data.append('filename', filename);
					// var data = {
					// 	action: action,
					// 	isAjax: true,
					// 	filename: evt.target.filename,
					// 	data: form_data,
					// 	attachmentId: attachmentId
					// };

					jQuery.ajax({
						type: 'POST',
						url: ajaxurl,
						contentType: false,
						processData: false,
						data: data,
						success: function (response) {
							jQuery('[postid=' + attachmentId + '] td').removeClass('wr2x-loading-file');
							jQuery('[postid=' + attachmentId + '] .wr2x-dragdrop').removeClass('wr2x-hover-drop');
							try {
								var data = jQuery.parseJSON(response);
							}
							catch (e) {
								alert("The server-side returned an abnormal response. Check your PHP error logs and also your browser console (WP Retina 2x will try to display it there).");
								console.debug(response);
								return;
							}
							if (wr2x_replace) {
								var imgSelector = '[postid=' + attachmentId + '] .wr2x-info-thumbnail img';
								jQuery(imgSelector).attr('src', jQuery(imgSelector).attr('src')+'?'+ Math.random());
							}
							if (wr2x_upload) {
								var imgSelector = '[postid=' + attachmentId + '] .wr2x-info-full img';
								jQuery(imgSelector).attr('src', jQuery(imgSelector).attr('src')+'?'+ Math.random());
							}
							if (data.success === false) {
								alert(data.message);
							}
							else {
								if ( wr2x_replace ) {
									wr2x_refresh_media_sizes(data.results);
								}
								else if ( wr2x_upload ) {
									wr2x_refresh_full(data.results);
								}
							}
						},
						error: function(XMLHttpRequest, textStatus, errorThrown) {
							jQuery('[postid=' + attachmentId + '] td').removeClass('wr2x-loading-file');
							jQuery('[postid=' + attachmentId + '] .wr2x-dragdrop').removeClass('wr2x-hover-drop');
							alert("An error occurred on the server-side. Please check your PHP error logs.");
					  }
					});
				}
				var file = files[0];
				if (file.size > maxPhpSize) {
					jQuery(this).removeClass('wr2x-hover-drop');
					alert( "Your PHP configuration only allows file upload of a maximum of " + (maxPhpSize / 1000000) + "MB." );
					return;
				}
				var postId = jQuery(evt.target).parents('.wr2x-file-row').attr('postid');
				jQuery(evt.target).parents('td').addClass('wr2x-loading-file');
				wr2x_uploadFile(file, postId, file.name);
			}

			jQuery(document).ready(function () {
				jQuery('.wr2x-dragdrop').on('dragenter', function (evt) {
					wr2x_stop_propagation(evt);
					jQuery(this).addClass('wr2x-hover-drop');
				});

				jQuery('.wr2x-dragdrop').on('dragover', function (evt) {
					wr2x_stop_propagation(evt);
					jQuery(this).addClass('wr2x-hover-drop');
				});

				jQuery('.wr2x-dragdrop').on('dragleave', function (evt) {
					wr2x_stop_propagation(evt);
					jQuery(this).removeClass('wr2x-hover-drop');
				});

				jQuery('.wr2x-dragdrop').on('dragexit', wr2x_stop_propagation);

				jQuery('.wr2x-dragdrop').each(function (index, elem) {
					this.addEventListener('drop', wr2x_filedropped);
				});

				jQuery('.wr2x-info, .wr2x-button-view').on('click', function (evt) {
					jQuery('#meow-modal-info-backdrop').css('display', 'block');
					jQuery('#meow-modal-info .content').html("");
					jQuery('#meow-modal-info .loading').css('display', 'block');
					jQuery('#meow-modal-info').css('display', 'block');
					jQuery('#meow-modal-info').focus();
					var postid = jQuery(evt.target).parents('.wr2x-info').attr('postid');
					if (!postid)
						postid = jQuery(evt.target).parents('.wr2x-file-row').attr('postid');
					wr2x_load_details(postid);
				});

				jQuery('#meow-modal-info .close, #meow-modal-info-backdrop').on('click', function (evt) {
					jQuery('#meow-modal-info').css('display', 'none');
					jQuery('#meow-modal-info-backdrop').css('display', 'none');
				});

				jQuery('.wr2x-info-full img').on('click', function (evt) {
					wr2x_delete_full( jQuery(evt.target).parents('.wr2x-file-row').attr('postid') );
				});

				jQuery('#meow-modal-info').bind('keydown', function (evt) {
					if (evt.keyCode === 27) {
						jQuery('#meow-modal-info').css('display', 'none');
						jQuery('#meow-modal-info-backdrop').css('display', 'none');
					}
				});
			});

		</script>
		<?php
	}

	/**
	 *
	 * AJAX SERVER-SIDE
	 *
	 */

	// Using issuesOnly, only the IDs with a PENDING status will be processed
	function wp_ajax_wr2x_list_all( $issuesOnly ) {
		$issuesOnly = intval( $_POST['issuesOnly'] );
		if ( $issuesOnly == 1 ) {
			$ids = $this->core->get_issues();
			echo json_encode(
				array(
					'success' => true,
					'message' => "List of issues only.",
					'ids' => $ids,
					'total' => count( $ids )
			) );
			die;
		}
		$reply = array();
		try {
			$ids = array();
			$total = 0;
			global $wpdb;
			$postids = $wpdb->get_col( "
				SELECT p.ID
				FROM $wpdb->posts p
				WHERE post_status = 'inherit'
				AND post_type = 'attachment'
				AND ( post_mime_type = 'image/jpeg' OR
					post_mime_type = 'image/png' OR
					post_mime_type = 'image/gif' )
			" );
			foreach ($postids as $id) {
				if ( $this->core->is_ignore( $id ) )
					continue;
				array_push( $ids, $id );
				$total++;
			}
			echo json_encode(
				array(
					'success' => true,
					'message' => "List of everything.",
					'ids' => $ids,
					'total' => $total
			) );
			die;
		}
		catch (Exception $e) {
			echo json_encode(
				array(
					'success' => false,
					'message' => $e->getMessage()
			) );
			die;
		}
	}

	function wp_ajax_wr2x_delete_full( $pleaseReturn = false ) {

		if ( !isset( $_POST['attachmentId'] ) ) {
			echo json_encode(
				array(
					'success' => false,
					'message' => __( "The attachment ID is missing.", 'wp-retina-2x' )
				)
			);
			die();
		}
		$attachmentId = intval( $_POST['attachmentId'] );
		$originalfile = get_attached_file( $attachmentId );
		$pathinfo = pathinfo( $originalfile );
		$retina_file = trailingslashit( $pathinfo['dirname'] ) . $pathinfo['filename'] . $this->core->retina_extension() . $pathinfo['extension'];
		if ( $retina_file && file_exists( $retina_file ) )
			unlink( $retina_file );

		// RESULTS FOR RETINA DASHBOARD
		$info = $this->core->html_get_basic_retina_info_full( $attachmentId, $this->core->retina_info( $attachmentId ) );
		$results[$attachmentId] = $info;

		// Return if that's not the final step.
		if ( $pleaseReturn )
			return $info;

		echo json_encode(
			array(
				'results' => $results,
				'success' => true,
				'message' => __( "Full retina file deleted.", 'wp-retina-2x' )
			)
		);
		die();
	}

	function wp_ajax_wr2x_delete() {

		if ( !isset( $_POST['attachmentId'] ) ) {
			echo json_encode(
				array(
					'success' => false,
					'message' => __( "The attachment ID is missing.", 'wp-retina-2x' )
				)
			);
			die();
		}

		// Information for the retina version of the full-size
		$attachmentId = intval( $_POST['attachmentId'] );
		$results_full[$attachmentId] = $this->wp_ajax_wr2x_delete_full( true );

		$this->core->delete_attachment( $attachmentId, true );
		$meta = wp_get_attachment_metadata( $attachmentId );

		// RESULTS FOR RETINA DASHBOARD
		$this->core->update_issue_status( $attachmentId );
		$info = $this->core->html_get_basic_retina_info( $attachmentId, $this->core->retina_info( $attachmentId ) );
		$results[$attachmentId] = $info;
		echo json_encode(
			array(
				'results' => $results,
				'results_full' => $results_full,
				'success' => true,
				'message' => __( "Retina files deleted.", 'wp-retina-2x' )
			)
		);
		die();
	}

	function wp_ajax_wr2x_retina_details() {
		if ( !isset( $_POST['attachmentId'] ) ) {
			echo json_encode(
				array(
					'success' => false,
					'message' => __( "The attachment ID is missing.", 'wp-retina-2x' )
				)
			);
			die();
		}

		$attachmentId = intval( $_POST['attachmentId'] );
		$info = $this->core->html_get_details_retina_info( $attachmentId, $this->core->retina_info( $attachmentId ) );
		echo json_encode(
			array(
				'result' => $info,
				'success' => true,
				'message' => __( "Details retrieved.", 'wp-retina-2x' )
			)
		);
		die();
	}

	function wp_ajax_wr2x_generate() {
		if ( !isset( $_POST['attachmentId'] ) ) {
			echo json_encode(
				array(
					'success' => false,
					'message' => __( "The attachment ID is missing.", 'wp-retina-2x' )
				)
			);
			die();
		}

		$attachmentId = intval( $_POST['attachmentId'] );
		$this->core->delete_attachment( $attachmentId, false );

		// Regenerate the Thumbnails
		$file = get_attached_file( $attachmentId );
		$meta = wp_generate_attachment_metadata( $attachmentId, $file );
		wp_update_attachment_metadata( $attachmentId, $meta );

		// Regenerate Retina
		//$meta = wp_get_attachment_metadata( $attachmentId );
		$this->core->generate_images( $meta );

		// RESULTS FOR RETINA DASHBOARD
		$info = $this->core->html_get_basic_retina_info( $attachmentId, $this->core->retina_info( $attachmentId ) );
		$results[$attachmentId] = $info;
		echo json_encode(
			array(
				'results' => $results,
				'success' => true,
				'message' => __( "Retina files generated.", 'wp-retina-2x' )
			)
		);
		die();
	}

	function check_get_ajax_uploaded_file() {
			if ( !current_user_can('upload_files') ) {
			echo json_encode( array(
				'success' => false,
				'message' => __( "You do not have permission to upload files.", 'wp-retina-2x' )
			));
			die();
		}

		$tmpfname = $_FILES['file']['tmp_name'];

		// Check if it is an image
		$file_info = getimagesize( $tmpfname );
		if ( empty( $file_info ) ) {
			$this->core->log( "The file is not an image or the upload went wrong." );
			unlink( $tmpfname );
			echo json_encode( array(
				'success' => false,
				'message' => __( "The file is not an image or the upload went wrong.", 'wp-retina-2x' )
			));
			die();
		}

		$filedata = wp_check_filetype_and_ext( $tmpfname, $_POST['filename'] );
		if ( $filedata["ext"] == "" ) {
			$this->core->log( "You cannot use this file (wrong extension? wrong type?)." );
			unlink( $current_file );
			echo json_encode( array(
				'success' => false,
				'message' => __( "You cannot use this file (wrong extension? wrong type?).", 'wp-retina-2x' )
			));
			die();
		}

		$this->core->log( "The temporary file was written successfully." );
		return $tmpfname;
	}

	function wp_ajax_wr2x_upload() {
		try {
			$tmpfname = $this->check_get_ajax_uploaded_file();
			$attachmentId = (int) $_POST['attachmentId'];
			$meta = wp_get_attachment_metadata( $attachmentId );
			$current_file = get_attached_file( $attachmentId );
			$pathinfo = pathinfo( $current_file );
			$basepath = $pathinfo['dirname'];
			$retinafile = trailingslashit( $pathinfo['dirname'] ) . $pathinfo['filename'] . $this->core->retina_extension() . $pathinfo['extension'];

			if ( file_exists( $retinafile ) )
				unlink( $retinafile );

			// Insert the new file and delete the temporary one
			list( $width, $height ) = getimagesize( $tmpfname );

			if ( !$this->core->are_dimensions_ok( $width, $height, $meta['width'] * 2, $meta['height'] * 2 ) ) {
				echo json_encode( array(
					'success' => false,
					'message' => "This image has a resolution of ${width}×${height} but your Full Size image requires a retina image of at least " . ( $meta['width'] * 2 ) . "x" . ( $meta['height'] * 2 ) . "."
				));
				die();
			}
			$this->core->resize( $tmpfname, $meta['width'] * 2, $meta['height'] * 2, null, $retinafile );
			chmod( $retinafile, 0644 );
			unlink( $tmpfname );

			// Get the results
			$info = $this->core->retina_info( $attachmentId );
			$this->core->update_issue_status( $attachmentId );
			$results[$attachmentId] = $this->core->html_get_basic_retina_info_full( $attachmentId, $info );
		}
		catch (Exception $e) {
			echo json_encode( array(
				'success' => false,
				'results' => null,
				'message' => __( "Error: " . $e->getMessage(), 'wp-retina-2x' )
			));
			die();
		}
		echo json_encode( array(
			'success' => true,
			'results' => $results,
			'message' => __( "Uploaded successfully.", 'wp-retina-2x' )
		));
		die();
	}

	function wp_ajax_wr2x_replace() {
		$tmpfname = $this->check_get_ajax_uploaded_file();
		$attachmentId = (int) $_POST['attachmentId'];
		$meta = wp_get_attachment_metadata( $attachmentId );
		$current_file = get_attached_file( $attachmentId );
		$this->core->delete_attachment( $attachmentId, false );
		$pathinfo = pathinfo( $current_file );
		$basepath = $pathinfo['dirname'];

		// Let's clean everything first
		if ( wp_attachment_is_image( $attachmentId ) ) {
			$sizes = $this->core->get_image_sizes();
			foreach ($sizes as $name => $attr) {
				if ( isset( $meta['sizes'][$name] ) && isset( $meta['sizes'][$name]['file'] ) && file_exists( trailingslashit( $basepath ) . $meta['sizes'][$name]['file'] ) ) {
					$normal_file = trailingslashit( $basepath ) . $meta['sizes'][$name]['file'];
					$pathinfo = pathinfo( $normal_file );
					$retina_file = trailingslashit( $pathinfo['dirname'] ) . $pathinfo['filename'] . $this->core->retina_extension() . $pathinfo['extension'];

					// Test if the file exists and if it is actually a file (and not a dir)
					// Some old WordPress Media Library are sometimes broken and link to directories
					if ( file_exists( $normal_file ) && is_file( $normal_file ) )
						unlink( $normal_file );
					if ( file_exists( $retina_file ) && is_file( $retina_file ) )
						unlink( $retina_file );
				}
			}
		}
		if ( file_exists( $current_file ) )
			unlink( $current_file );

		// Insert the new file and delete the temporary one
		rename( $tmpfname, $current_file );
		chmod( $current_file, 0644 );

		// Generate the images
		wp_update_attachment_metadata( $attachmentId, wp_generate_attachment_metadata( $attachmentId, $current_file ) );
		$meta = wp_get_attachment_metadata( $attachmentId );
		$this->core->generate_images( $meta );

		// Get the results
		$info = $this->core->retina_info( $attachmentId );
		$results[$attachmentId] = $this->core->html_get_basic_retina_info( $attachmentId, $info );

		echo json_encode( array(
			'success' => true,
			'results' => $results,
			'message' => __( "Replaced successfully.", 'wp-retina-2x' )
		));
		die();
	}

}

?>
