/* global wdceoData, ajaxurl */
( function ( $, data, wp, _ ) {
	$( function () {
		const $table = $( '.wdevs-coe-template-columns' ),
			$tbody = $( '.wdevs-coe-template-columns-rows' ),
			$save_button = $( '.wdevs-coe-template-columns-save' ),
			$row_template = wp.template( 'wdevs-coe-template-columns-row' ),
			$blank_template = wp.template(
				'wdevs-coe-template-columns-row-blank'
			),
			$configure_button = $(
				'.wdevs-coe-template-configure-column-button'
			);

		// Backbone model
		( Column = Backbone.Model.extend( {
			changes: {},
			logChanges( changedRows ) {
				const changes = this.changes || {};

				_.each( changedRows.columns, function ( row, id ) {
					changes.columns = changes.columns || { columns: {} };
					changes.columns[ id ] = _.extend(
						changes.columns[ id ] || { column_id: id },
						row
					);
				} );

				if ( typeof changedRows.name !== 'undefined' ) {
					changes.name = changedRows.name;
				}

				this.changes = changes;
				this.trigger( 'change:columns' );
			},
			save() {
				$.post(
					window.wdceoData.ajaxUrl,
					{
						action: window.wdceoData.templateColumnsAction,
						nonce: window.wdceoData.nonce,
						changes: this.changes,
						id: data.id,
					},
					this.onSaveResponse,
					'json'
				);
			},
			onSaveResponse( response, textStatus ) {
				if ( 'success' === textStatus ) {
					if ( response.success ) {
						if ( response.data.id !== data.id ) {
							data.id = response.data.id;
							if ( window.history.pushState ) {
								window.history.pushState(
									{},
									'',
									'admin.php?page=wc-settings&tab=wdevs_coe&section=templates&template_id=' +
										response.data.id
								);
							}
						}
						column.set(
							'selectableColumns',
							response.data.selectableColumns
						);
						column.set(
							'columnsFlattened',
							response.data.columnsFlattened
						);
						column.trigger( 'change:columns' );
						column.changes = {};
						column.trigger( 'saved:columns' );
						window.onbeforeunload = null;
					} else {
						window.alert( data.strings.save_failed );
					}
				}
			},
		} ) ),
			// Backbone view
			( ColumnView = Backbone.View.extend( {
				rowTemplate: $row_template,
				initialize() {
					this.listenTo(
						this.model,
						'change:columns',
						this.setUnloadConfirmation
					);
					this.listenTo(
						this.model,
						'saved:columns',
						this.clearUnloadConfirmation
					);
					this.listenTo( this.model, 'saved:columns', this.render );
					this.listenTo( this.model, 'rerender', this.render );
					$tbody.on(
						'sortupdate',
						{ view: this },
						this.updateModelOnSort
					);
					$( window ).on(
						'beforeunload',
						{ view: this },
						this.unloadConfirmation
					);
					$save_button.on( 'click', { view: this }, this.onSubmit );

					$( document.body ).on(
						'input change',
						'#name',
						{ view: this },
						this.onUpdateTemplate
					);

					$( document.body ).on(
						'click',
						'.wdevs-coe-template-configure-column-button',
						{ view: this },
						this.onAddColumn
					);
					$( document.body ).on(
						'wc_backbone_modal_response',
						_.bind( this.onConfigureColumnSubmitted, this )
					);
					$( document.body ).on(
						'wc_backbone_modal_before_remove',
						this.onCloseConfigureColumn
					);
					$( document.body ).on(
						'wc_backbone_modal_validation',
						{ view: this },
						this.validateFormArguments
					);
					$( document.body ).on(
						'wc_backbone_modal_loaded',
						{ view: this },
						this.onModalLoaded
					);
					$( document.body ).on(
						'change',
						'.wc-backbone-modal-content select[name="category_id"]',
						{ view: this },
						this.onCategoryChange
					);
					$( document.body ).on(
						'change',
						'.wc-backbone-modal-content select[name="field_id"]',
						{ view: this },
						this.onFieldChange
					);
				},
				onUpdateTemplate( event ) {
					const view = event.data.view,
						model = view.model,
						value = $( this ).val(),
						$target = $( event.target ),
						attribute = $target.data( 'attribute' ),
						changes = {};

					event.preventDefault();
					changes[ attribute ] = value;
					model.set( attribute, value );
					model.logChanges( changes );
					view.render();
				},
				block() {
					$( this.el ).block( {
						message: null,
						overlayCSS: {
							background: '#fff',
							opacity: 0.6,
						},
					} );
				},
				unblock() {
					$( this.el ).unblock();
				},
				render() {
					const columns = this.model.get( 'columnsFlattened' );
					const view = this;

					this.$el.empty();
					this.unblock();

					if ( _.size( columns ) ) {
						const columnsArray = Object.entries( columns );

						const sortedColumns = _.sortBy(
							columnsArray,
							( [ key, data ] ) => parseInt( data.order, 10 )
						);

						sortedColumns.forEach( ( [ key, rowData ] ) => {
							rowData.column_id = key;

							view.$el.append( view.rowTemplate( rowData ) );
							const $tr = view.$el.find(
								`tr[data-id="${ key }"]`
							);

							$tr.find(
								'.wc-shipping-zone-method-title > a'
							).replaceWith(
								'<span>' +
									$tr
										.find(
											'.wc-shipping-zone-method-title > a'
										)
										.text() +
									'</span>'
							);
							const $del = $tr.find(
								'.wc-shipping-zone-method-delete'
							);
							$tr.find(
								'.wc-shipping-zone-method-title .row-actions'
							)
								.empty()
								.html( $del );
						} );
						this.$el
							.find( '.wdevs-ceo-column-edit' )
							.on(
								'click',
								{ view: this },
								this.onConfigureColumn
							);
						this.$el
							.find( '.wdevs-ceo-column-delete' )
							.on( 'click', { view: this }, this.onDeleteRow );
					} else {
						view.$el.append( $blank_template );
					}
				},
				onSubmit( event ) {
					$save_button.addClass( 'is-busy' );
					event.data.view.block();
					event.data.view.model.save();
					event.preventDefault();
				},
				onDeleteRow( event ) {
					const column_id = $( this ).closest( 'tr' ).data( 'id' );

					event.preventDefault();

					if (
						window.confirm(
							data.strings.delete_column_confirmation
						)
					) {
						const model = event.data.view.model,
							columnsFlattened = model.get( 'columnsFlattened' ),
							column = columnsFlattened[ column_id ];
						changes = {};

						if ( column ) {
							const column_data = {
								category_id: column.category_id,
								deleted: 'deleted',
							};

							changes.columns = {};
							changes.columns[ column_id ] = column_data;

							columnView.block();
							$configure_button.prop( 'disabled', true );
							$configure_button.addClass( 'is-busy' );

							model.logChanges( changes );

							model.save();
						}
					}
				},
				setUnloadConfirmation() {
					this.needsUnloadConfirm = true;
					$save_button.prop( 'disabled', false );
					$save_button.removeClass( 'is-busy' );
				},
				clearUnloadConfirmation() {
					this.needsUnloadConfirm = false;
					$save_button.attr( 'disabled', 'disabled' );

					$configure_button.prop( 'disabled', false );
					$configure_button.removeClass( 'is-busy' );
				},
				unloadConfirmation( event ) {
					if ( event.data.view.needsUnloadConfirm ) {
						event.returnValue =
							data.strings.unload_confirmation_msg;
						window.event.returnValue =
							data.strings.unload_confirmation_msg;
						return data.strings.unload_confirmation_msg;
					}
				},
				updateModelOnSort( event ) {
					const view = event.data.view,
						model = view.model,
						columns = model.get( 'columnsFlattened' ),
						changes = {
							columns: {},
						};

					_.each( columns, function ( column, column_id ) {
						const old_position = parseInt( column.order, 10 );

						const new_position = parseInt(
							$table
								.find( 'tr[data-id="' + column_id + '"]' )
								.index() + 1,
							10
						);

						if ( old_position !== new_position ) {
							//columns[column_id].order = new_position;
							// changes.columns = changes.columns || {columns: {}};
							changes.columns[ column_id ] = {
								order: new_position,
								category_id: column.category_id,
							};
						}
					} );

					if ( _.size( changes ) ) {
						view.block();
						$configure_button.prop( 'disabled', true );
						$configure_button.addClass( 'is-busy' );

						model.logChanges( changes );

						model.save();
					}
				},
				onConfigureColumn( event ) {
					const column_id = $( this ).closest( 'tr' ).data( 'id' );

					event.preventDefault();
					$( this ).WCBackboneModal( {
						template: 'wdevs-coe-template-configure-column',
						variable: {
							template_id: data.id,
							column_id,
							action: 'edit',
						},
					} );
				},
				onConfigureColumnSubmitted( event, target, posted_data ) {
					if ( 'wdevs-coe-template-configure-column' === target ) {
						const view = this,
							model = view.model,
							// columns = _.clone(model.get('columnsFlattened')) || {},
							changes = {};

						const modalContent = $( '.wc-backbone-modal-content' );

						//When editing; select is disabled, and value is not passed in formData
						if ( ! posted_data.category_id ) {
							const $categorySelect = modalContent.find(
								'select[name="category_id"]'
							);
							if ( $categorySelect.length ) {
								posted_data.category_id = $categorySelect.val();
							}
						}

						//When editing; select is disabled, and value is not passed in formData
						if ( ! posted_data.field_id ) {
							const $fieldSelect = modalContent.find(
								'select[name="field_id"]'
							);
							if ( $fieldSelect.length ) {
								posted_data.field_id = $fieldSelect.val();
							}
						}

						const column_id =
							posted_data.column_id || posted_data.field_id;

						const column_data = {
							category_id: posted_data.category_id,
							name: posted_data.name,
						};

						// columns[column_id] = column_data;

						changes.columns = {};
						changes.columns[ column_id ] = column_data;

						view.block();
						$configure_button.prop( 'disabled', true );
						$configure_button.addClass( 'is-busy' );

						model.logChanges( changes );

						model.save();
					}
				},
				onAddColumn( event ) {
					event.preventDefault();
					$( this ).WCBackboneModal( {
						template: 'wdevs-coe-template-configure-column',
						variable: {
							template_id: data.id,
							action: 'create',
							column_id: null,
						},
					} );
				},
				onModalLoaded( event, target ) {
					if ( target === 'wdevs-coe-template-configure-column' ) {
						const modalContent = $( '.wc-backbone-modal-content' );

						const $categorySelect = modalContent.find(
							'select[name="category_id"]'
						);
						const $emptyCategoryOption = $categorySelect
							.find( 'option[value=""]' )
							.clone();
						$categorySelect.empty().append( $emptyCategoryOption );

						let newColumn = true;

						const modalData = modalContent.data();
						if ( modalData && modalData.column_id ) {
							const model = event.data.view.model,
								columnsFlattened =
									model.get( 'columnsFlattened' ),
								column =
									columnsFlattened[ modalData.column_id ];
							if ( column ) {
								newColumn = false;
								if (
									data.selectableColumns &&
									data.selectableColumns[ column.category_id ]
								) {
									if (
										data.selectableColumns[
											column.category_id
										].fields &&
										data.selectableColumns[
											column.category_id
										].fields[ modalData.column_id ]
									) {
										const categoryOption = {
											value: column.category_id,
											text: data.selectableColumns[
												column.category_id
											].name,
											selected: true,
										};

										const fieldOption = {
											value: modalData.column_id,
											text: data.selectableColumns[
												column.category_id
											].fields[ modalData.column_id ]
												.name,
											selected: true,
										};

										if ( $categorySelect ) {
											$categorySelect.empty();
											$categorySelect.append(
												$( '<option>', categoryOption )
											);
											$categorySelect.trigger( 'input' );
											$categorySelect.prop(
												'disabled',
												true
											);
										}

										const $fieldSelect = modalContent.find(
											'select[name="field_id"]'
										);

										if ( $fieldSelect ) {
											$fieldSelect.empty();
											$fieldSelect.append(
												$( '<option>', fieldOption )
											);
											$fieldSelect.trigger( 'input' );
											$fieldSelect.prop(
												'disabled',
												true
											);
										}

										const rowData = {
											template_id: data.id,
											category_id: column.category_id,
											field_id: modalData.column_id,
											name: column.name,
										};

										$( '.wc-backbone-modal-content' )
											.find( 'input' )
											.each( function () {
												const attribute =
													$( this ).data(
														'attribute'
													);
												if ( attribute ) {
													$( this ).val(
														rowData[ attribute ]
													);
													$( this ).trigger(
														'input'
													);
												}
											} );
									}
								}
							}
						}

						if ( newColumn && data.selectableColumns ) {
							for ( const [
								categoryKey,
								categoryData,
							] of Object.entries( data.selectableColumns ) ) {
								if ( categoryData.fields ) {
									const hasSelectableField = Object.values(
										categoryData.fields
									).some(
										( field ) => field.selectable === true
									);

									if ( hasSelectableField ) {
										$categorySelect.append(
											$( '<option>', {
												value: categoryKey,
												text: categoryData.name,
											} )
										);
									}
								}
							}
							$categorySelect.val( '' ).trigger( 'change' );
						}
					}
				},
				onCategoryChange( event ) {
					const modalContent = $( '.wc-backbone-modal-content' );

					const $fieldSelect = modalContent.find(
						'select[name="field_id"]'
					);
					const $fieldContainer = modalContent.find(
						'.wdevs-coe-column-field'
					);
					const category_id = $( this ).val();

					$fieldContainer.hide();

					if ( category_id ) {
						if (
							data.selectableColumns &&
							data.selectableColumns[ category_id ] &&
							data.selectableColumns[ category_id ].fields
						) {
							const $emptyOption = $fieldSelect
								.find( 'option[value=""]' )
								.clone();
							$fieldSelect.empty().append( $emptyOption );

							Object.entries(
								data.selectableColumns[ category_id ].fields
							).forEach( ( [ fieldKey, fieldData ] ) => {
								if ( fieldData.selectable !== false ) {
									$fieldSelect.append(
										$( '<option>', {
											value: fieldKey,
											text: fieldData.field || fieldKey,
										} )
									);
								}
							} );

							$fieldContainer.show();
						}
					}

					$fieldSelect.val( '' ).trigger( 'change' );
				},
				onFieldChange( event ) {
					const modalContent = $( '.wc-backbone-modal-content' );
					const $nameInput =
						modalContent.find( 'input[name="name"]' );
					const $nameContainer = modalContent.find(
						'.wdevs-coe-column-name'
					);
					const $helpText = modalContent.find( '#field-help-text' );
					const selectedValue = $( this ).val();

					$nameContainer.hide();
					$nameInput.val( '' );

					if ( selectedValue ) {
						const $categorySelect = modalContent.find(
							'select[name="category_id"]'
						);
						if ( $categorySelect.length ) {
							const selectedCategoryId = $categorySelect.val();
							if (
								data.selectableColumns &&
								data.selectableColumns[ selectedCategoryId ] &&
								data.selectableColumns[ selectedCategoryId ]
									.fields
							) {
								for ( const [
									fieldId,
									fieldProperties,
								] of Object.entries(
									data.selectableColumns[ selectedCategoryId ]
										.fields
								) ) {
									if ( fieldId === selectedValue ) {
										$nameInput.val( fieldProperties.name );
										if ( fieldProperties.description ) {
											$helpText.html(
												fieldProperties.description
											);
										}
										break;
									}
								}
							}
						}

						$nameContainer.show();
					}

					$nameInput.trigger( 'input' );
				},
				validateFormArguments( event, target, formData ) {
					if ( target === 'wdevs-coe-template-configure-column' ) {
						const nextButton = document.getElementById( 'btn-ok' );
						nextButton.disabled = true;
						nextButton.classList.add( 'disabled' );

						const modalContent = $( '.wc-backbone-modal-content' );

						//When editing; select is disabled, and value is not passed in formData
						if ( ! formData.category_id ) {
							const $categorySelect = modalContent.find(
								'select[name="category_id"]'
							);
							if ( $categorySelect.length ) {
								formData.category_id = $categorySelect.val();
							}
						}

						//When editing; select is disabled, and value is not passed in formData
						if ( ! formData.field_id ) {
							const $fieldSelect = modalContent.find(
								'select[name="field_id"]'
							);
							if ( $fieldSelect.length ) {
								formData.field_id = $fieldSelect.val();
							}
						}

						if (
							formData.category_id &&
							formData.field_id &&
							formData.name
						) {
							nextButton.disabled = false;
							nextButton.classList.remove( 'disabled' );
						}
					}
				},
				onCloseConfigureColumn(
					event,
					target,
					post_data,
					addButtonCalled
				) {
					if ( target === 'wc-modal-shipping-method-settings' ) {
						const btnData = $( '#btn-ok' ).data();

						if (
							! addButtonCalled &&
							btnData &&
							btnData.status === 'new'
						) {
							shippingMethodView.block();

							const view = shippingMethodView,
								model = view.model,
								methods = _.indexBy(
									model.get( 'methods' ),
									'column_id'
								),
								changes = {},
								column_id = post_data.column_id;

							// Remove method to zone via ajax call
							$.post( {
								url:
									ajaxurl +
									( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) +
									'action=woocommerce_shipping_zone_remove_method',
								data: {
									nonce: data.nonce,
									column_id,
									zone_id: data.zone_id,
								},
								success( { data } ) {
									delete methods[ column_id ];
									changes.methods =
										changes.methods || data.methods;
									model.set( 'methods', methods );
									model.logChanges( changes );
									view.clearUnloadConfirmation();
									view.render();
									shippingMethodView.unblock();
								},
								error( jqXHR, textStatus, errorThrown ) {
									window.alert(
										data.strings.remove_method_failed
									);
									shippingMethodView.unblock();
								},
								dataType: 'json',
							} );
						}
					}
				},
			} ) ),
			( column = new Column( {
				columnsFlattened: data.columnsFlattened,
				name: data.name,
			} ) ),
			( columnView = new ColumnView( {
				model: column,
				el: $tbody,
			} ) );

		if ( $table.length ) {
			columnView.render();
			$tbody.sortable( {
				items: 'tr',
				cursor: 'move',
				axis: 'y',
				handle: 'td.wc-shipping-zone-method-sort',
				scrollSensitivity: 40,
			} );
		}

		$( '.wdevs-coe-template-delete' ).each( function () {
			$( this ).on( 'click', function ( event ) {
				event.preventDefault();

				const templateId = $( this ).closest( 'tr' ).data( 'id' );

				if (
					templateId &&
					window.confirm(
						window.wdceoData.strings.delete_template_confirmation
					)
				) {
					$.post(
						window.wdceoData.ajaxUrl,
						{
							action: window.wdceoData.templateDeleteAction,
							nonce: window.wdceoData.nonce,
							id: templateId,
						},
						function ( response ) {
							if ( response.success ) {
								window.location.reload();
							} else if ( response.data.message ) {
								alert( response.data.message );
							}
						},
						'json'
					);
				}
			} );
		} );
	} );
} )( jQuery, wdceoData, wp, _ );
