/* filter is a javascript builtin, but extjs calls it also filter */
Ext.define('PVE.form.VMSelector', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.vmselector',

    mixins: {
	field: 'Ext.form.field.Field',
    },

    allowBlank: true,
    selectAll: false,
    isFormField: true,

    plugins: 'gridfilters',

    store: {
	model: 'PVEResources',
	sorters: 'vmid',
    },

    userCls: 'proxmox-tags-circle',

    columnsDeclaration: [
	{
	    header: 'ID',
	    dataIndex: 'vmid',
	    width: 80,
	    filter: {
		type: 'number',
	    },
	},
	{
	    header: gettext('Node'),
	    dataIndex: 'node',
	},
	{
	    header: gettext('Status'),
	    dataIndex: 'status',
	    filter: {
		type: 'list',
	    },
	},
	{
	    header: gettext('Name'),
	    dataIndex: 'name',
	    flex: 1,
	    filter: {
		type: 'string',
	    },
	},
	{
	    header: gettext('Pool'),
	    dataIndex: 'pool',
	    filter: {
		type: 'list',
	    },
	},
	{
	    header: gettext('Type'),
	    dataIndex: 'type',
	    width: 120,
	    renderer: function(value) {
		if (value === 'qemu') {
		    return gettext('Virtual Machine');
		} else if (value === 'lxc') {
		    return gettext('LXC Container');
		}

		return '';
	    },
	    filter: {
		type: 'list',
		store: {
		    data: [
			{ id: 'qemu', text: gettext('Virtual Machine') },
			{ id: 'lxc', text: gettext('LXC Container') },
		    ],
		    un: function() {
			// Due to EXTJS-18711. we have to do a static list via a store but to avoid
			// creating an object, we have to have an empty pseudo un function
		    },
		},
	    },
	},
	{
	    header: gettext('Tags'),
	    dataIndex: 'tags',
	    renderer: tags => PVE.Utils.renderTags(tags, PVE.UIOptions.tagOverrides),
	    flex: 1,
	},
	{
	    header: 'HA ' + gettext('Status'),
	    dataIndex: 'hastate',
	    flex: 1,
	    filter: {
		type: 'list',
	    },
	},
    ],

    // should be a list of 'dataIndex' values, if 'undefined' all declared columns will be included
    columnSelection: undefined,

    selModel: {
	selType: 'checkboxmodel',
	mode: 'SIMPLE',
    },

    checkChangeEvents: [
	'selectionchange',
	'change',
    ],

    listeners: {
	selectionchange: function() {
	    // to trigger validity and error checks
	    this.checkChange();
	},
    },

    getValue: function() {
	var me = this;
	if (me.savedValue !== undefined) {
	    return me.savedValue;
	}
	var sm = me.getSelectionModel();
	var selection = sm.getSelection();
	var values = [];
	var store = me.getStore();
	selection.forEach(function(item) {
	    // only add if not filtered
	    if (store.findExact('vmid', item.data.vmid) !== -1) {
		values.push(item.data.vmid);
	    }
	});
	return values;
    },

    setValueSelection: function(value) {
	let me = this;

	let store = me.getStore();
	let notFound = [];
	let selection = value.map(item => {
	    let found = store.findRecord('vmid', item, 0, false, true, true);
	    if (!found) {
		if (Ext.isNumeric(item)) {
		    notFound.push(item);
		} else {
		    console.warn(`invalid item in vm selection: ${item}`);
		}
	    }
	    return found;
	}).filter(r => r);

	for (const vmid of notFound) {
	    let rec = store.add({
		vmid,
		node: 'unknown',
	    });
	    selection.push(rec[0]);
	}

	let sm = me.getSelectionModel();
	if (selection.length) {
	    sm.select(selection);
	} else {
	    sm.deselectAll();
	}
	// to correctly trigger invalid class
	me.getErrors();
    },

    setValue: function(value) {
	let me = this;
	value ??= [];
	if (!Ext.isArray(value)) {
	    value = value.split(',').filter(v => v !== '');
	}

	let store = me.getStore();
	if (!store.isLoaded()) {
	    me.savedValue = value;
	    store.on('load', function() {
		me.setValueSelection(value);
		delete me.savedValue;
	    }, { single: true });
	} else {
	    me.setValueSelection(value);
	}
	return me.mixins.field.setValue.call(me, value);
    },

    getErrors: function(value) {
	let me = this;
	if (!me.isDisabled() && me.allowBlank === false &&
	    me.getValue().length === 0) {
	    me.addBodyCls(['x-form-trigger-wrap-default', 'x-form-trigger-wrap-invalid']);
	    return [gettext('No VM selected')];
	}

	me.removeBodyCls(['x-form-trigger-wrap-default', 'x-form-trigger-wrap-invalid']);
	return [];
    },

    setDisabled: function(disabled) {
	let me = this;
	let res = me.callParent([disabled]);
	me.getErrors();
	return res;
    },

    initComponent: function() {
	let me = this;

	let columns = me.columnsDeclaration.filter((column) =>
	    me.columnSelection ? me.columnSelection.indexOf(column.dataIndex) !== -1 : true,
	).map((x) => x);

	me.columns = columns;

	me.callParent();

	me.getStore().load({ params: { type: 'vm' } });

	if (me.nodename) {
	    me.getStore().addFilter({
		property: 'node',
		exactMatch: true,
		value: me.nodename,
	    });
	}

	// only show the relevant guests by default
	if (me.action) {
	    var statusfilter = '';
	    switch (me.action) {
		case 'startall':
		    statusfilter = 'stopped';
		    break;
		case 'stopall':
		    statusfilter = 'running';
		    break;
	    }
	    if (statusfilter !== '') {
		me.getStore().addFilter([{
		    property: 'template',
		    value: 0,
		}, {
		    id: 'x-gridfilter-status',
		    operator: 'in',
		    property: 'status',
		    value: [statusfilter],
		}]);
	    }
	}

	if (me.selectAll) {
	    me.mon(me.getStore(), 'load', function() {
		me.getSelectionModel().selectAll(false);
	    });
	}
    },
});


Ext.define('PVE.form.VMComboSelector', {
    extend: 'Proxmox.form.ComboGrid',
    alias: 'widget.vmComboSelector',

    valueField: 'vmid',
    displayField: 'vmid',

    autoSelect: false,
    editable: true,
    anyMatch: true,
    forceSelection: true,

    store: {
	model: 'PVEResources',
	autoLoad: true,
	sorters: 'vmid',
	filters: [{
	    property: 'type',
	    value: /lxc|qemu/,
	}],
    },

    listConfig: {
	width: 600,
	plugins: 'gridfilters',
	columns: [
	    {
		header: 'ID',
		dataIndex: 'vmid',
		width: 80,
		filter: {
		    type: 'number',
		},
	    },
	    {
		header: gettext('Name'),
		dataIndex: 'name',
		flex: 1,
		filter: {
		    type: 'string',
		},
	    },
	    {
		header: gettext('Node'),
		dataIndex: 'node',
	    },
	    {
		header: gettext('Status'),
		dataIndex: 'status',
		filter: {
		    type: 'list',
		},
	    },
	    {
		header: gettext('Pool'),
		dataIndex: 'pool',
		hidden: true,
		filter: {
		    type: 'list',
		},
	    },
	    {
		header: gettext('Type'),
		dataIndex: 'type',
		width: 120,
		renderer: function(value) {
		    if (value === 'qemu') {
			return gettext('Virtual Machine');
		    } else if (value === 'lxc') {
			return gettext('LXC Container');
		    }

		    return '';
		},
		filter: {
		    type: 'list',
		    store: {
			data: [
			    { id: 'qemu', text: gettext('Virtual Machine') },
			    { id: 'lxc', text: gettext('LXC Container') },
			],
			un: function() { /* due to EXTJS-18711 */ },
		    },
		},
	    },
	    {
		header: 'HA ' + gettext('Status'),
		dataIndex: 'hastate',
		hidden: true,
		flex: 1,
		filter: {
		    type: 'list',
		},
	    },
	],
    },
});
