jQuery(
	function ( $ ) {
		$.easing.easeInOutQuad = function(e,f,a,h,g){return -h*(f/=g)*(f-2)+a};
		var DomControllerFactory = (
				function () {
					return {
						create: function ( /*Function*/ constructor ) {
							return {
								instance: function ( elt, id ) {
									return new constructor( elt, id );
								}
							};
						}
					};
				}
			()),
			Selectors = (
				function () {
					var _query = function ( /*Object*/ hash, prefix, /*String*/ query ) {
							if( hash[query] ) return prefix + hash[query];
							else return log( sprintf( "%s doesn\'t exist in hash", query ) );
						},
						klass = function ( /*Object*/ hash, /*String*/ query ) {
							return _query( hash, '.', query );
						},
						id = function ( /*Object*/ hash, /*String*/ query ) {
							return _query( hash, '#', query );
						},
						singlton = {
							name: name,
							klass: klass,
							id: id
						};
					return singlton;
				}
			)(),
			sprintf = function ( text ){ // resource: https://gist.github.com/1013686
				var i = 1, args = arguments;
				return text.replace( /%s/g, function ( pattern ) {
					return ( i < args.length ) ? args[ i++ ] : "";
				});
			},
			log = function () {
				window.console && console.log( sprintf.apply( undefined, Array.prototype.slice.call( arguments ) ) );
			},
			TARGETS = {
				icons_bar:			"b-gallery-icons",
				icon:				"b-gallery__icon",
				icon_selected:		"b-gallery__icon_selected",
				icon_pic:			"b-gallery__icon__pic",
				bigpic:				"b-gallery-bigpic",
				bigpic_idle:		"b-gallery-bigpic_idle",
				bigpic_hasnext:		"b-gallery-bigpic_hasnext",
				bigpic_wrap: 		"b-gallery-bigpic-wrapper"
			},
			Icons_bar = (
				function() {
					var	$icons_bar = $( Selectors.klass( TARGETS, "icons_bar" ) ),
						$icons = $( Selectors.klass( TARGETS, "icon" ), $icons_bar ),
						$initial_bigpic = $( Selectors.klass( TARGETS, "bigpic" ) ),
						current_bigpic_uri = $initial_bigpic.attr( "src" ),
						icons_controllers = [],
						bigpic_controllers = [],
						Icon = DomControllerFactory.create( 
							function( elt, id ) {
								var uri = elt.attr( "href" ),
									selected_class = TARGETS[ "icon_selected" ],
									state = elt.hasClass( selected_class ),
									click = function ( /*Event*/ evt ) {
										evt.preventDefault();
										icons_bar_controller.update( id );
									},
									controller = {
										update: function ( /*Boolean*/ new_state ) {
											if ( new_state == state ) return;
											elt.toggleClass( selected_class );
											state = new_state;
										},
										uri: function () {
											return uri;
										},
										state: function () {
											return state;
										}
									};
								elt.bind( "click", click );
								return controller;
							}
						),
						BigPic = DomControllerFactory.create( 
							function ( elt, id ) {
								var elt = $( elt ),
									idle_class = TARGETS[ "bigpic_idle" ],
									state = ! elt.hasClass( idle_class ),
									anim_duration = 400,
									easing = "easeInOutQuad",
									click = function ( /*Event*/ evt ) {
										var next = id == bigpic_controllers.length - 1 ? 0 : id + 1;
										icons_bar_controller.update( next );
									},
									controller = {
										update: function ( /*Boolean*/ new_state ) {
											if ( new_state == state ) return;
											if ( new_state ) elt.removeClass( idle_class );
											elt.stop().animate( 
												{ opacity: new_state ? 1 : 0 },
												{
													duration: anim_duration,
													easing: easing,
													complete: function () {
														if ( ! new_state ) elt.addClass( idle_class );
													}
												}
											);
											state = new_state;
										}
									};
								elt.css( { opacity: state ? 1 : 0 } );
								elt.bind( "click", click );
								return controller;
							}
						),
						add_bigpic = function ( /*String*/ new_pic_uri ) {
							var new_bigpic = $( "<img>" );
							new_bigpic.attr( "src", new_pic_uri ) 
									  .attr( "alt", $initial_bigpic.attr( "alt" ) )
									  .attr( "class", $initial_bigpic.attr( "class" ) )
									  .addClass( TARGETS[ "bigpic_idle" ] )
									  .insertAfter( $( Selectors.klass( TARGETS, "bigpic" ) ).last() );
							return new_bigpic;
						},
						display_multiple_bigpics_as_links = function () {
							if ( bigpic_controllers.length > 1 ) {
								var bigpic_class = Selectors.klass( TARGETS, "bigpic" ),
									hasnext_class = TARGETS[ "bigpic_hasnext" ];
								$( bigpic_class ).addClass( hasnext_class );
							}
						},
						ie_quirks_fix = function () {
							if( $.browser.msie ) {
								var maxw = 0,
									maxh = 0,
									bigpics = $( Selectors.klass( TARGETS, "bigpic" ) ),
									bigpic_wrap = $( Selectors.klass( TARGETS, "bigpic_wrap" ) );
								bigpics.each( 
									function ( index, item ) {
										var thisw = $( item ).outerWidth(),
											thish = $( item ).outerHeight();
										maxw = thisw > maxw ? thisw : maxw;
										maxh = thish > maxh ? thish : maxh;
									}
								);
								bigpic_wrap.width( maxw )
										   .height( maxh );
							}
						},
						icons_bar_controller = {
							init: function () {
								$.each( $icons,
									function ( index, item ) {
										var $icon = $(item),
											icon = Icon.instance( $icon, index ),
											icon_uri = icon.uri(),
											$bigpic = icon_uri == current_bigpic_uri ? $initial_bigpic : add_bigpic( icon_uri ),
											bigpic = BigPic.instance( $bigpic, index );
										icons_controllers.push( icon );
										bigpic_controllers.push( bigpic );
									}
								);
								display_multiple_bigpics_as_links();
								ie_quirks_fix();
							},
							update: function ( /*Number*/ id ) {
								$.each( icons_controllers, 
									function( index, item ) {
										var new_state = index == id,
											bigpic = bigpic_controllers[ index ];
										item.update( new_state );
										bigpic.update( new_state );
									}
								);
							}
						};
					return icons_bar_controller;
				}
			)();
		Icons_bar.init();
	}
);
