/* =======================================
   EXPORT CENTER
   ======================================= */

import { Blocker } from '../../../../../../atum-stock-manager-for-woocommerce/assets/js/src/components/_blocker';
import EntitySelector from './_entity-selector';
import ExportSettings from '../../config/_export-settings';
import FileTypeSelector from './_file-type-selector';
import Globals from './_globals';
import FieldSelector from './_field-selector';
import SelectedField from './_selected-field';
import TemplateSettings from './_template-settings';

export default class ExportCenter {
	
	entitySelObj: EntitySelector;
	fileTypeSelObj: FileTypeSelector;
	mainEntityFieldSelector: FieldSelector;
	subentitiesFieldSelector: FieldSelector;
	templateSettings: TemplateSettings;
	
	constructor(
		private settings: ExportSettings,
		private globals: Globals,
	) {
		
		this.entitySelObj = new EntitySelector(this.settings, this.globals);
		this.fileTypeSelObj = new FileTypeSelector(this.globals);
		this.templateSettings = new TemplateSettings(this.settings, this.globals);
		
		this.bindEvents();
		
	}
	
	bindEvents() {
		
		this.entitySelObj.$elem
			.on('atum-export-entity-data-loaded', () => this.loadEntityData() )
			.on('atum-export-entity-data-unloaded', () => this.unloadEntityData() );
		
		this.fileTypeSelObj.$elem.on('atum-export-file-type-selected', () => this.loadEntityData() );
		
		// Clear all the selected fields at once.
		this.globals.$selectionSection.on('click', '.clear-all-fields', () => this.clearAllFields() );
		
		// Save the template.
		this.templateSettings.$form.on('atum-export-save-template', () => this.saveTemplate() );
		
		// Run Export.
		this.globals.$exportActions.on('click', '#run-export', (evt: JQueryEventObject) => {
			evt.preventDefault();
			this.templateSettings.validateSubmission('atum-export-run-export');
		} );
		
		this.templateSettings.$form.on('atum-export-run-export', () => {
			
			const exportParams: any = {
				entity   : this.entitySelObj.entitySelected,
				file_type: this.fileTypeSelObj.fileTypeSelected,
				settings : this.templateSettings.$form.serialize(),
				data     : this.globals.getTemplateData(),
			};
			
			this.globals.runExport(exportParams);
			
		} );
		
	}
	
	/**
	 * Load the selected entity data
	 */
	loadEntityData() {
		
		const $exportSelectorWrapper: JQuery = this.globals.$entitySection.find('.export-selector .selection-wrapper');
		
		$exportSelectorWrapper.find('.alert').remove();
		
		// Both selectors (file type and entity) must have values in order to continue.
		if (!this.fileTypeSelObj.fileTypeSelected) {
			$exportSelectorWrapper.append(`<div class="alert alert-info">${ this.settings.get('selectFileType') }</div>`);
			this.globals.$fieldSelectors.hide();
		}
		else if ($.isEmptyObject(this.entitySelObj.entityData)) {
			
			if (this.entitySelObj.entitySelected) {
				$exportSelectorWrapper.append(`<div class="alert alert-danger">${ this.settings.get('invalidEntityData') }</div>`);
			}
			
			this.globals.$fieldSelectors.show();
			
		}
		else {
			
			if ($.isEmptyObject(this.mainEntityFieldSelector)) {
				this.globals.loadEntities({...this.entitySelObj.entityData});
				this.createFieldSelectors();
				this.globals.summary.maybeCreateSummary();
			}
			
			this.globals.$fieldSelectors.show();
			
		}
		
	}
	
	/**
	 * Unload the selected entity data + clean up
	 */
	unloadEntityData() {
		this.clearAllFields(true);
		this.cleanUpEntity();
		this.globals.summary.maybeCreateSummary();
	}
	
	/**
	 * Clean Up the loaded entity from memory
	 */
	cleanUpEntity() {
		this.globals.$fieldSelectors.empty();
		this.globals.mainEntity = null;
		this.globals.subentities = [];
		this.globals.entities = [];
		this.globals.selectedFields = [];
		this.mainEntityFieldSelector = null;
		this.subentitiesFieldSelector = null;
	}
	
	/**
	 * Create the field selectors for the main entity and its subentities
	 */
	createFieldSelectors() {
	
		// Add the main entity's field selector.
		this.mainEntityFieldSelector = new FieldSelector([this.globals.mainEntity], this.globals, this.settings);
		this.globals.$fieldSelectors.append( this.mainEntityFieldSelector.$elem );
		this.mainEntityFieldSelector.addCaption();
	
		// Add the subentities' field selector.
		this.subentitiesFieldSelector = new FieldSelector(this.globals.subentities, this.globals, this.settings);
		this.globals.$fieldSelectors.append( this.subentitiesFieldSelector.$elem );
		this.subentitiesFieldSelector.addCaption();
		
		this.manageEntitySectionPosition();
		
		// Click the selected items once the lists are added to the DOM.
		if (this.globals.selectedFields.length) {
			this.globals.selectedFields.forEach(($elem: JQuery) => $elem.click());
			this.globals.rearrangePositionSelects();
		}
		
	}
	
	/**
	 * Update the entity section position when scrolling
	 */
	manageEntitySectionPosition() {
		
		const entitySectionPosition: number = this.globals.$entitySection.offset().top,
		      adminBarHeight: number        = $('#wpadminbar').outerHeight() || 0,
		      $scrollWrapper: JQuery        = this.globals.$entitySection.find('.export-init-scroll-wrapper');
		
		$(window).on('scroll', () => {
			
			// Give it a delay to avoid flickering.
			setTimeout( () => {
				
				const yScrollPos: number          = window.pageYOffset + adminBarHeight,
				      displacement: number        = yScrollPos - entitySectionPosition,
				      entitySectionHeight: number = this.globals.$entitySection.height(),
				      scrollWrapperHeight: number = $scrollWrapper.outerHeight();
				
				let top: number = 0;
				
				// If the entity section components reached the section's bottom, don't continue displacing it.
				if ( (scrollWrapperHeight + displacement ) >= entitySectionHeight) {
					top = entitySectionHeight - scrollWrapperHeight;
				}
				else if (yScrollPos > entitySectionPosition) {
					top = $scrollWrapper.scrollTop() + displacement;
				}
				
				$scrollWrapper.css('top', top);
				
			}, 200);
			
		});
		
	}
	
	/**
	 * Clear all the fields added to the template
	 *
	 * @param {boolean} force
	 */
	clearAllFields(force: boolean = false) {
		
		const $selectedFields: JQuery = this.globals.$entitySection.find('.select-list > li.selected');
		
		if (force) {
			
			$selectedFields.each( (index: number, elem: Element) => {
				const selectedField: SelectedField = $(elem).data('selected-field');
				selectedField.remove(true);
			});
			
		}
		else {
			
			this.globals.swal({
				title              : this.settings.get('areYouSure'),
				text               : this.settings.get('removeAllFields'),
				type               : 'warning',
				showCancelButton   : true,
				confirmButtonText  : this.settings.get('continue'),
				cancelButtonText   : this.settings.get('cancel'),
				reverseButtons     : true,
				allowOutsideClick  : false
			})
			.then( () =>  {
				
				$selectedFields.each( (index: number, elem: Element) => {
					const selectedField: SelectedField = $(elem).data('selected-field');
					selectedField.remove(true);
				});
				
			} )
			.catch(this.globals.swal.noop);
			
		}
		
	}
	
	/**
	 * Submit the settings' form and save the template
	 */
	saveTemplate() {
		
		const templateId: number = this.templateSettings.newTemplate === true ? null : this.globals.templateId;
		
		$.ajax({
			url       : window['ajaxurl'],
			dataType  : 'json',
			method    : 'post',
			data      : {
				token      : this.settings.get('nonce'),
				action     : 'aep_save_template',
				template_id: templateId,
				entity     : this.entitySelObj.entitySelected,
				file_type  : this.fileTypeSelObj.fileTypeSelected,
				settings   : this.templateSettings.$form.serialize(),
				data       : this.globals.getTemplateData(),
			},
			beforeSend: () => Blocker.block(this.globals.$contentWrapper),
			success   : (response: any) => {
				
				if (response.success === true) {
					
					const templateId: number = parseInt( response.data.templateId );
					
					// Add/Update the template title and ID.
					this.globals.$templateDataSection.find('.template-title').text(response.data.templateName);
					this.globals.$templateDataSection.data('id', templateId);
					this.globals.templateId = templateId;
					
					this.globals.swal({
						title            : this.settings.get('success'),
						text             : response.data.message,
						type             : 'success',
						confirmButtonText: this.settings.get('ok'),
						allowOutsideClick: false,
					})
					.then( () => {
						
						// If the user is saving a new template from a default one, move to the saved template.
						if (this.templateSettings.newTemplate === true && this.globals.$templateDataSection.data('type') === 'default') {
							$.address.parameter('template_id', this.globals.templateId);
						}
						
					});
					
				}
				else {
					
					this.globals.swal({
						title            : this.settings.get('error'),
						text             : response.data,
						type             : 'error',
						confirmButtonText: this.settings.get('ok'),
						allowOutsideClick: false,
					});
					
				}
				
				Blocker.unblock(this.globals.$contentWrapper);
				
			},
			error     : () => Blocker.unblock(this.globals.$contentWrapper),
		});
		
	}
	
}

