( function( Backbone, $ ) {
	"use strict";

	if ( ! $( '#wpr-review-items-app' ).length ) {
		return;
	}

	var App = {
		Models: {},
		Collections: {},
		Views: {}
	};

	App.Models.Item = Backbone.Model.extend({
		defaults: function() {
			return {
				id: '',
				item_id: '',
				wp_review_item_title: '',
				wp_review_item_star: 0,
				wp_review_item_color: $( '#wpr-review-color-value' ).val(),
				wp_review_item_inactive_color: $( '#wpr-review-inactive-color-value' ).val(),
				type: $( '#wpr-review-type-2' ).val() || wprVars.globalReviewType
			};
		}
	});

	App.Collections.Items = Backbone.Collection.extend({
		model: App.Models.Item
	});

	App.Views.ItemView = Backbone.View.extend({
		template: wp.template( 'wpr-review-item' ),

		className: 'wpr-review-item',

		initialize: function() {
			this.model.on( 'destroy', this.remove, this );
		},

		events: {
			'click .delete-item': 'remove',
			'change .input-title': 'changeTitle',
			'change .input-star': 'changeScore'
		},

		render: function() {
			var _this = this,
				data;

			data = this.model.toJSON();
			data.itemNameSetting = wp.template( 'wpr-review-item-name' )( data );
			data.itemColorSetting = wp.template( 'wpr-review-item-color' )( data );
			data.itemInactiveColorSetting = wp.template( 'wpr-review-item-inactive-color' )( data );
			if ( $( '#tmpl-wpr-review-item-' + data.type + '-rating' ).length ) {
				data.itemRatingSetting = wp.template( 'wpr-review-item-' + data.type + '-rating' )( data );
			} else {
				data.itemRatingSetting = wp.template( 'wpr-review-item-rating' )( data );
			}
			this.$el.html( this.template( data ) );

			this.$( '.input-color' ).wpColorPicker({
				change: function( ev, ui ) {
					var color = ui.color.toString();
					_this.$( '.wpr-star-input-wrapper' ).css({ color: color });
					_this.$( '.input-star[data-type="circle"]' ).trigger( 'configure', { fgColor: color, inputColor: color } );
					_this.$( '.wpr-input-wrapper.ui-slider .ui-slider-range' ).css({ backgroundColor: color });
					_this.$( '.thumbs-up-icon' ).css({ color: color });
					_this.model.set( 'wp_review_item_color', color );
				}
			});

			this.$( '.input-inactive-color' ).wpColorPicker({
				change: function( ev, ui ) {
					var color = ui.color.toString();
					_this.$( '.wpr-star-input-wrapper .stars-bg' ).css({ color: color });
					_this.$( '.input-star[data-type="circle"]' ).trigger( 'configure', { bgColor: color } );
					_this.$( '.wpr-input-wrapper.ui-slider' ).css({ backgroundColor: color });
					_this.$( '.thumbs-down-icon' ).css({ color: color });
					_this.model.set( 'wp_review_item_inactive_color', color );
				}
			});

			function validateValue( value, min, max ) {
				value = parseFloat( value );
				if ( isNaN( value ) || min !== undefined && value < min || max !== undefined && value > max ) {
					_this.$el.find( '.input-star, .input-star-display' ).addClass( 'review-value-incorrect' );
				} else {
					_this.$el.find( '.input-star, .input-star-display' ).removeClass( 'review-value-incorrect' );
				}
			}

			switch ( this.model.get( 'type' ) ) {
				case 'star':
					var _this = this;

					this.$( '.input-star' ).wprStarInput({
						ready: function( wrapper, options ) {
							this.appendTo( this.closest( '.col-2' ).next() );
						},
						callback: function( value ) {
							validateValue( value, 0, wprVars.reviewTypes.star.max );
							_this.model.set( 'wp_review_item_star', value );
						}
					});
					break;

				case 'circle':
					this.$( '.input-star' ).wprCircleInput({
						width: 50,
						displayInput: false,
						ready: function( options ) {
							var $input = $( '<input type="text" size="4" class="input-star-display">' ),
								_this = this;
							$input.val( this.val() );
							this.closest( '.col-2' ).next().append( $input );

							$input.on( 'change', function() {
								var value = $( this ).val();
								validateValue( value, 0, wprVars.reviewTypes.circle.max );
								_this.val( value ).trigger( 'change' );
							});
						},
						callback: function( value ) {
							value = Math.round( value );
							validateValue( value, 0, wprVars.reviewTypes.circle.max );
							_this.model.set( 'wp_review_item_star', value );
							this.closest( '.col-2' ).next().find( '.input-star-display' ).val( value );
						}
					});
					break;

				case 'percentage':
					this.$( '.input-star' ).wprPercentageInput({
						ready: function( wrapper, options ) {
							this.appendTo( this.closest( '.col-2' ).next() );
						},
						callback: function( value ) {
							this.val( value );
							validateValue( value, 0, wprVars.reviewTypes.percentage.max );
							_this.model.set( 'wp_review_item_star', value );
						}
					});
					break;

				case 'point':
					this.$( '.input-star' ).wprPointInput({
						ready: function( wrapper, options ) {
							this.appendTo( this.closest( '.col-2' ).next() );
						},
						callback: function( value ) {
							this.val( value );
							validateValue( value, 0, wprVars.reviewTypes.point.max );
							_this.model.set( 'wp_review_item_star', value );
						}
					});
					break;

				case 'thumbs':
					this.$( '.thumbs-input' ).on( 'input propertychange', function() {
						var up, down, value;
						up = parseInt( _this.$( '.thumbs-up-input' ).val() || 0 );
						down = parseInt( _this.$( '.thumbs-down-input' ).val() || 0 );
						value = 100 * up / ( up + down );
						value = Math.round( value * 10 ) / 10;
						_this.model.set( 'wp_review_item_star', value );
						_this.$( '.input-star' ).val( value );
					});
			}

			this.$el.attr( 'data-id', this.model.get( 'id' ) );
			return this;
		},

		remove: function() {
			collection.remove( this.model );
		},

		changeTitle: function( ev ) {
			this.model.set( 'wp_review_item_title', ev.target.value );
		},

		changeScore: function( ev ) {
			this.model.set( 'wp_review_item_star', parseFloat( ev.target.value ) );
		}
	});

	App.Views.AppView = Backbone.View.extend({
		el: '#wpr-review-items-app',

		initialize: function() {
			this.render();
			this.collection.on( 'add', this.renderOne, this );
			this.collection.on( 'remove', this.remove, this );
			this.collection.on( 'add', this.calculateTotal, this );
			this.collection.on( 'change', this.calculateTotal, this );
			this.collection.on( 'remove', this.calculateTotal, this );
		},

		events: {
			'click .add-item': 'addItem',
			'change #wpr-review-type-2': 'changeType'
		},

		render: function() {
			this.$( '.wpr-review-items' ).html( '' );
			this.collection.each( this.renderOne, this );
			this.calculateTotal();
			this.$( '.wpr-review-items' ).sortable({
				handle: '.wpr-icon-move'
			});
			return this;
		},

		renderOne: function( item ) {
			var view = new App.Views.ItemView({ model: item });
			this.$( '.wpr-review-items' ).append( view.render().el );
		},

		calculateTotal: function() {
			var total = 0,
				count = this.collection.length;

			if ( count ) {
				_.each( this.collection.models, function( item ) {
					total += ! isNaN( item.get( 'wp_review_item_star' ) ) ? parseFloat( item.get( 'wp_review_item_star' ) * 1 ) : 0;
				});
				total = Math.round( total * 100 / count ) / 100;
			}

			this.$( '.input-total' ).val( total );
		},

		remove: function( item ) {
			this.$el.find( '.wpr-review-item[data-id="' + item.get( 'id' ) + '"]' ).remove();
		},

		addItem: function() {
			var model = new App.Models.Item();
			model.set( 'id', 'a' + parseInt( Math.random() * 100 ) );
			this.collection.add( model );
		},

		changeType: function( ev ) {
			var type = ev.target.value;
			if ( type == 'none' ) {
				return;
			}
			_.each( this.collection.models, function( item ) {
				item.set( 'type', type );
			});
			this.render();
		}
	});

	function onSelectType() {
		$( '#wpr-review-type-2' ).val( $( this ).val() ).trigger( 'change' );
	}
	$( '#wp_review_type' ).on( 'change', onSelectType );

	// App initialize.
	var items = $( '#wpr-review-items-data' ).val();
	items = items ? JSON.parse( items ) : [];
	items.map( function( item, index ) {
		item.item_id = item.id;
		item.id = index;
		return item;
	});

	var collection = new App.Collections.Items( items );

	var appView = new App.Views.AppView({
		collection: collection
	});
})( Backbone, jQuery );
