/*
 * SPDX-FileCopyrightText: 2014-2026 Univention GmbH
 * SPDX-License-Identifier: AGPL-3.0-only
 */

/*global define*/

define([
	"dojo/_base/declare",
	"dojo/_base/lang",
	"dojo/_base/array",
	"dojo/aspect",
	"dojox/html/entities",
	"umc/tools",
	"umc/dialog",
	"umc/store",
	"umc/widgets/Grid",
	"umc/widgets/Page",
	"umc/widgets/StandbyMixin",
	"umc/widgets/SearchForm",
	"umc/i18n!umc/modules/schoolwizards"
], function(declare, lang, array, aspect, entities, tools, dialog, store, Grid, Page, StandbyMixin, SearchForm, _) {

	return declare("umc.modules.schoolwizards.Grid", [Page, StandbyMixin], {

		fullWidth: true,
		autoSearch: true,
		autoSearchOnChange: true,
		udmLinkEnabled: null,
		module: null,
		umcpCommand: null,
		moduleFlavor: null,
		sortFields: ['school', 'name'],
		idProperty: '$dn$',

		buildRendering: function() {
			this.inherited(arguments);

			this._grid = this.getGrid();
			this.buildSearchForm();

			this.addChild(this._searchForm);
			this.addChild(this._grid);
		},

		startup: function() {
			this.inherited(arguments);
			this._grid.resize();
		},

		getSelectedSchool: function() {
			var widget = this._searchForm.getWidget('school');
			if (widget) {
				var val = widget.get('value');
				if (val === '/') {
					val = '';
				}
				return val;
			}
		},

		getSelectedType: function() {
			var widget = this._searchForm.getWidget('type');
			if (widget) {
				var val = widget.get('value');
				if (val === 'all') {
					val = '';
				}
				return val;
			}
		},

		getGrid: function() {
			var grid = new Grid({
				region: 'center',
				footerFormatter: lang.hitch(this, 'getGridFooter'),
				defaultAction: this.getGridDefaultAction(),
				actions: this.getGridActions(),
				columns: this.getGridColumns(),
				moduleStore: this.getGridStore(),
				sortIndex: 1,
				allowHTML: false,
				standbyDuring: lang.hitch(this, 'standbyDuring')
			});
			return grid;
		},

		getGridDefaultAction: function() {
			return 'edit';
		},

		getGridActions: function() {
			return [this.getGridAddAction(), this.getGridEditAction(), this.getGridDeleteAction()];
		},

		getGridAddAction: function() {
			return {
				name: 'add',
				label: _('Add'),
				description: _('Add a new %s', this.objectNameSingular),
				iconClass: 'plus',
				isContextAction: false,
				isStandardAction: true,
				callback: lang.hitch(this, 'createObject')
			};
		},

		getGridEditAction: function() {
			return {
				name: 'edit',
				label: _('Edit'),
				description: _('Edit the %s.', this.objectNameSingular),
				iconClass: 'edit-2',
				isStandardAction: true,
				isMultiAction: false,
				callback: lang.hitch(this, 'editObjects')
			};
		},

		getGridDeleteAction: function() {
			return {
				name: 'delete',
				label: _('Delete'),
				description: _('Deleting the selected %s.', this.objectNamePlural),
				isStandardAction: true,
				isMultiAction: true,
				iconClass: 'trash',
				callback: lang.hitch(this, 'confirmObjectDeletion')
			};
		},

		getGridColumnsWithSchool: function() {
			var columns = [];
			if (this.getSelectedSchool() === '') {
				columns.push({
					name: 'school',
					label: _('School')
				});
			}
			columns = this.getGridColumns().concat(columns);
			return columns;
		},

		getGridColumns: function() {
			return [];
		},

		getGridStore: function() {
			var s = store(this.idProperty, this.basePath || this.moduleFlavor, this.moduleFlavor);
			s.umcpCommand = lang.hitch(this, 'umcpCommand');
			return s;
		},

		getGridFooter: function(nItems, nItemsTotal) {
			var map = {
				nSelected: nItems,
				nTotal: nItemsTotal,
				objPlural: this.objectNamePlural,
				objSingular: this.objectNameSingular
			};
			if (0 === nItemsTotal) {
				return _('No %(objPlural)s could be found', map);
			} else if (1 === nItems) {
				return _('%(nSelected)d %(objSingular)s of %(nTotal)d selected', map);
			} else {
				return _('%(nSelected)d %(objPlural)s of %(nTotal)d selected', map);
			}
		},

		buildSearchForm: function() {
			var widgets = this.getSearchWidgets();
			var buttons = this.getSearchButtons();
			var layout = this.getSearchLayout();

			this._searchForm = new SearchForm({
				region: 'top',
				hideSubmitButton: true,
				widgets: widgets,
				layout: layout,
				buttons: buttons,
				onSearch: lang.hitch(this, 'filter')
			});
			this._searchForm.ready().then(lang.hitch(this, function() {
				// re-run the search when the school selection is changed. The watch is
				// attached after the form is ready, so the initial value assignment does
				// not trigger it; the initial search is handled by autoSearch below.
				let schoolWidget = this._searchForm.getWidget('school');
				if (schoolWidget) {
					schoolWidget.watch('value', lang.hitch(this, function() {
						if (this.autoSearchOnChange) {
							this._searchForm.submit();
						}
					}));
				}
			}));
			if (this.autoSearch) {
				this._searchForm.ready().then(lang.hitch(this, function() {
					this.filter({type: 'all'});
					if (!this.schools.length) {
						return;
					}
					var handler = aspect.before(this._grid, 'onFilterDone', lang.hitch(this, function(success) {
						handler.remove();
						if (this._grid.getAllItems().length === 0) {
							var title = _('No %(objectNamePlural)s found', {objectNamePlural: this.objectNamePlural});
							var txt = _('No %(objectNamePlural)s were found.', {objectNamePlural: this.objectNamePlural});
							txt += ' ' + _('Would you like to create %(firstObject)s now?', {firstObject: this.firstObject});
							dialog.confirm(txt, [{
								name: 'cancel',
								label: _('Cancel')
							}, {
								name: 'add',
								'default': true,
								label: _('Create')
							}], title).then(lang.hitch(this, function(response) {
								if (response === 'add') {
									this.createObject();
								}
							}));
						}
						return arguments;
					}));
				}));
			}
		},

		getSearchButtons: function() {
			return [{
				name: 'submit',
				label: _('Search')
			}];
		},

		getSearchLayout: function() {
			return null;
		},

		getSearchWidgets: function() {
			return [];
		},

		filter: function(props) {
			props.school = this.getSelectedSchool();
			this._grid.filter(props);
			this._grid.set('columns', this.getGridColumnsWithSchool());
		},

		createObject: function() {
			this.createWizard({
				editMode: false,
				$dn$: null,
				school: this.getSelectedSchool(),
				selectedSchool: this.getSelectedSchool(),
				type: this.getSelectedType(),
				itemType: tools.capitalize(this.objectNameSingular),
				objectType: null,
				'class': 'umcCard'
			});
		},

		editObjects: function(ids, items) {
			var item = items[0];
			this.createWizard({
				editMode: true,
				$dn$: item.$dn$,
				school: item.school,
				selectedSchool: item.schools ? this.getSelectedSchool(): item.school,  // User with multiple schools must have the view of the currently selected school!
				type: item.type,
				itemType: tools.capitalize(this.objectNameSingular),
				objectType: item.objectType
			});
		},

		createWizard: function(props) {
			var wizard = new this.createObjectWizard(lang.mixin({
				udmLinkEnabled: this.udmLinkEnabled,
				store: this._grid.moduleStore,
				schools: this.schools,
				umcpCommand: lang.hitch(this, 'umcpCommand')
			}, props));
			this.module.addChild(wizard);
			this.module.selectChild(wizard);
			var closeWizard = lang.hitch(this, function() {
				this.module.selectChild(this);
				this.module.removeChild(wizard);
			});
			wizard.on('cancel', closeWizard);
			wizard.on('finished', closeWizard);

			// TODO: test if still works... why does it exists?
			if (!props.editMode && 'onShow' in wizard) {
				// send a reload command to wizard
				this.module.on('show', lang.hitch(this, function(evt) {
					wizard.onShow();
				}));
			}
		},

		getObjectIdName: function(item) {
			return '';
		},

		getDeleteConfirmMessage: function(objects) {
			var msg = _('Please confirm to delete the %(num)d selected %(objectNamePlural)s.', {num: objects.length, objectNamePlural: this.objectNamePlural});
			if (objects.length === 1) {
				msg = _('Please confirm to delete %(objectNameSingular)s "%(objectName)s".', {objectNameSingular: this.objectNameSingular, objectName: entities.encode(this.getObjectIdName(objects[0]))});
			}
			return msg;
		},

		confirmObjectDeletion: function(ids, objects) {
			dialog.confirm('<p>' + this.getDeleteConfirmMessage(objects) + '</p>',
				[{
				name: 'cancel',
				'default': true,
				label: _('Cancel')
			}, {
				name: 'delete',
				label: _('Delete')
			}]).then(lang.hitch(this, function(response) {
				if (response === 'delete') {
					this.deleteObjects(ids, objects);
				}
			}));
		},

		deleteObjects: function(ids, objects) {
			var transaction = this._grid.moduleStore.transaction();
			array.forEach(objects, function(object) {
				this._grid.moduleStore.remove({
					$dn$: object.$dn$,
					school: object.school,
					remove_from_school: object.schools ? this.school : object.school  // if it's a user on multiple schools we need to remove him only from one school -> send the selected school
				});
			}, this);
			return this.standbyDuring(transaction.commit()).then(
				function(response) {
					var errorMessages = [];
					array.forEach(response, function(res) {
						if (res.result) {
							errorMessages.push(res.result.message);
						}
					});
					if (errorMessages.length) {
						dialog.alert(entities.encode(errorMessages.join(' ')));
						return false;
					}
					return true;
				},
				function() {
					return false;
				}
			);
		}
	});
});
