/* jshint onevar: false, multistr: true */
/* global _wpMediaViewsL10n, _wpGalleryWidgetAdminSettings */

(function($){
	var $ids;
	var $thumbs;

	$(function(){
		$( document.body ) .on( 'click', '.gallery-widget-choose-images', function( event ) {
			event.preventDefault();

			var widget_form = $( this ).closest( 'form, .form' );

			$ids    = widget_form.find( '.gallery-widget-ids' );
			$thumbs	= widget_form.find( '.gallery-widget-thumbs' );

			var idsString = $ids.val();

			var attachments = getAttachments( idsString );

			var selection   = null;
			var editing     = false;

			if ( attachments ) {
				selection = getSelection( attachments );

				editing = true;
			}

			var options = {
				state: 'gallery-edit',
				title: wp.media.view.l10n.addMedia,
				multiple: true,
				editing: editing,
				selection: selection
			};

			var workflow = getWorkflow( options );

			workflow.open();
		});

		// Setup an onchange handler to toggle various options when changing style. The different style options
		// require different form inputs to be presented in the widget; this event will keep the UI in sync
		// with the selected style
		$( '.widget-inside' ).on( 'change', '.gallery-widget-style', setupStyleOptions);

		// Setup the Link To options for all forms currently on the page. Does the same as the onChange handler, but
		// is called once to display the correct form inputs for each widget on the page
		setupStyleOptions();
	});

	var media       = wp.media,
		l10n;

	// Link any localized strings.
	l10n = media.view.l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n;

	/**
	 * wp.media.view.MediaFrame.GalleryWidget
	 *
	 * This behavior can be very nearly had by setting the workflow's state to 'gallery-edit', but
	 * we cannot use the custom WidgetGalleryEdit controller with it (must overide createStates(),
	 * which is necessary to disable the sidebar gallery settings in the media browser)
	 */
	media.view.MediaFrame.GalleryWidget = media.view.MediaFrame.Post.extend({
		createStates: function() {
			var options = this.options;

			// `CollectionEdit` and `CollectionAdd` were only introduced in r27214-core,
			// so they may not be available yet.
			if ( 'CollectionEdit' in media.controller ) {
				this.states.add([
					new media.controller.CollectionEdit({
						type:           'image',
						collectionType: 'gallery',
						title:           l10n.editGalleryTitle,
						SettingsView:    media.view.Settings.Gallery,
						library:         options.selection,
						editing:         options.editing,
						menu:           'gallery'
					}),
					new media.controller.CollectionAdd({
						type:           'image',
						collectionType: 'gallery',
						title:          l10n.addToGalleryTitle
					})
				]);
			} else {
				// If `CollectionEdit` is not available, then use the old approach.

				if ( ! ( 'WidgetGalleryEdit' in media.controller ) ) {
					// Remove the gallery settings sidebar when editing widgets.
					media.controller.WidgetGalleryEdit = media.controller.GalleryEdit.extend({
						gallerySettings: function( /*browser*/ ) {
							return;
						}
					});
				}

				this.states.add([
					new media.controller.WidgetGalleryEdit({
						library: options.selection,
						editing: options.editing,
						menu:    'gallery'
					}),
					new media.controller.GalleryAdd({ })
				]);
			}
		}
	});

	function setupStyleOptions(){
		$( '.widget-inside .gallery-widget-style' ).each( function( /*i*/ ){
			var style = $( this ).val();

			var form = $( this ).parents( 'form' );

			switch ( style ) {
				case 'slideshow':
					form.find( '.gallery-widget-link-wrapper' ).hide();
					form.find( '.gallery-widget-columns-wrapper' ).hide();

					break;

				default:
					form.find( '.gallery-widget-link-wrapper' ).show();
					form.find( '.gallery-widget-columns-wrapper' ).show();
			}
		});
	}

	/**
	 * Take a given Selection of attachments and a thumbs wrapper div (jQuery object)
	 * and fill it with thumbnails
	 */
	function setupThumbs( selection, wrapper ){
		wrapper.empty();

		var imageSize = _wpGalleryWidgetAdminSettings.thumbSize;

		selection.each( function( model ){
			var sizedUrl = model.get('url') + '?w=' + imageSize + '&h=' + imageSize + '&crop=true';

			var thumb = jQuery('<img>', { 'src' : sizedUrl, 'alt': model.get('title'), 'title': model.get('title'), 'width': imageSize, 'height': imageSize, 'class': 'thumb' });

			wrapper.append( thumb );
		});
	}

	/**
	 * Take a csv string of ids (as stored in db) and fetch a full Attachments collection
	 */
	function getAttachments( idsString ) {
		if ( ! idsString ) {
			return null;
		}

		// Found in /wp-includes/js/media-editor.js
		var shortcode = wp.shortcode.next( 'gallery', '[gallery ids="' + idsString + '"]' );

		// Ignore the rest of the match object, to give attachments() below what it expects
		shortcode     = shortcode.shortcode;

		var attachments = wp.media.gallery.attachments( shortcode );

		return attachments;
	}

	/**
	 * Take an Attachments collection and return a corresponding Selection model that can be
	 * passed to a MediaFrame to prepopulate the gallery picker
	 */
	function getSelection( attachments ) {
		var selection = new wp.media.model.Selection( attachments.models, {
			props:    attachments.props.toJSON(),
			multiple: true
		});

		selection.gallery = attachments.gallery;

		// Fetch the query's attachments, and then break ties from the
		// query to allow for sorting.
		selection.more().done( function() {
			// Break ties with the query.
			selection.props.set( { query: false } );
			selection.unmirror();
			selection.props.unset( 'orderby' );
		});

		return selection;
	}

	/**
	 * Create a media 'workflow' (MediaFrame). This is the main entry point for the media picker
	 */
	function getWorkflow( options ) {
		var workflow = new wp.media.view.MediaFrame.GalleryWidget( options );

		workflow.on( 'update', function( selection ) {
			var state = workflow.state();

			selection = selection || state.get( 'selection' );

			if ( ! selection ) {
				return;
			}

			// Map the Models down into a simple array of ids that can be easily imploded to a csv string
			var ids = selection.map( function( model ){
				return model.get( 'id' );
			} );

			var id_string = ids.join( ',' );

			$ids.val( id_string ).trigger( 'change' );

			setupThumbs( selection, $thumbs );
		}, this );

		workflow.setState( workflow.options.state );

		return workflow;
	}
})(jQuery);
