Ext.define('pbs-datastore-list', {
    extend: 'Ext.data.Model',
    fields: ['name', 'comment'],
    proxy: {
        type: 'proxmox',
        url: "/api2/json/admin/datastore",
    },
    idProperty: 'store',
});

Ext.define('pbs-tape-drive-list', {
    extend: 'Ext.data.Model',
    fields: ['name', 'changer'],
    proxy: {
        type: 'proxmox',
        url: "/api2/json/tape/drive",
    },
    idProperty: 'name',
});

Ext.define('PBS.store.NavigationStore', {
    extend: 'Ext.data.TreeStore',

    storeId: 'NavigationStore',

    root: {
	expanded: true,
	children: [
	    {
		text: gettext('Dashboard'),
		iconCls: 'fa fa-tachometer',
		path: 'pbsDashboard',
		leaf: true,
	    },
	    {
		text: gettext('Configuration'),
		iconCls: 'fa fa-gears',
		path: 'pbsSystemConfiguration',
		expanded: true,
		children: [
		    {
			text: gettext('Access Control'),
			iconCls: 'fa fa-key',
			path: 'pbsAccessControlPanel',
			leaf: true,
		    },
		    {
			text: gettext('Remotes'),
			iconCls: 'fa fa-server',
			path: 'pbsRemoteView',
			leaf: true,
		    },
		    {
			text: gettext('Certificates'),
			iconCls: 'fa fa-certificate',
			path: 'pbsCertificateConfiguration',
			leaf: true,
		    },
		    {
			text: gettext('Subscription'),
			iconCls: 'fa fa-support',
			path: 'pbsSubscription',
			leaf: true,
		    },
		],
	    },
	    {
		text: gettext('Administration'),
		iconCls: 'fa fa-wrench',
		path: 'pbsServerAdministration',
		expanded: true,
		leaf: false,
		children: [
		    {
			text: gettext('Shell'),
			iconCls: 'fa fa-terminal',
			path: 'pbsXtermJsConsole',
			leaf: true,
		    },
		    {
			text: gettext('Storage / Disks'),
			iconCls: 'fa fa-hdd-o',
			path: 'pbsStorageAndDiskPanel',
			leaf: true,
		    },
		],
	    },
	    {
		text: "Tape Backup",
		iconCls: 'pbs-icon-tape',
		id: 'tape_management',
		path: 'pbsTapeManagement',
		expanded: true,
		children: [],
	    },
	    {
		text: gettext('Datastore'),
		iconCls: 'fa fa-archive',
		id: 'datastores',
		path: 'pbsDataStores',
		expanded: true,
		expandable: false,
		leaf: false,
		children: [
		    {
			text: gettext('Add Datastore'),
			iconCls: 'fa fa-plus-circle',
			leaf: true,
			id: 'addbutton',
			virtualEntry: true,
		    },
		],
	    },
	],
    },
});

Ext.define('PBS.view.main.NavigationTree', {
    extend: 'Ext.list.Tree',
    xtype: 'navigationtree',

    controller: {
	xclass: 'Ext.app.ViewController',

	init: function(view) {
	    view.rstore = Ext.create('Proxmox.data.UpdateStore', {
		autoStart: true,
		interval: 15 * 1000,
		storeid: 'pbs-datastore-list',
		model: 'pbs-datastore-list',
	    });

	    view.rstore.on('load', this.onLoad, this);
	    view.on('destroy', view.rstore.stopUpdate);

	    if (view.tapeStore === undefined) {
		view.tapeStore = Ext.create('Proxmox.data.UpdateStore', {
		    autoStart: true,
		    interval: 60 * 1000,
		    storeid: 'pbs-tape-drive-list',
		    model: 'pbs-tape-drive-list',
		});
		view.tapeStore.on('load', this.onTapeDriveLoad, this);
		view.on('destroy', view.tapeStore.stopUpdate);
	    }
	},

	onTapeDriveLoad: function(store, records, success) {
	    if (!success) return;

	    let view = this.getView();
	    let root = view.getStore().getRoot();

	    records.sort((a, b) => a.data.name.localeCompare(b.data.name));

	    let list = root.findChild('id', 'tape_management', false);
	    let existingChildren = {};
	    for (const drive of records) {
		let path, text, iconCls;
		if (drive.data.changer !== undefined) {
		    text = drive.data.changer;
		    path = `Changer-${text}`;
		    iconCls = 'fa fa-exchange';
		} else {
		    text = drive.data.name;
		    path = `Drive-${text}`;
		    iconCls = 'pbs-icon-tape-drive';
		}
		existingChildren[path] = {
		    text,
		    path,
		    iconCls,
		    leaf: true,
		};
	    }

	    let paths = Object.keys(existingChildren).sort();

	    let oldIdx = 0;
	    for (let newIdx = 0; newIdx < paths.length; newIdx++) {
		let newPath = paths[newIdx];
		// find index to insert
		while (oldIdx < list.childNodes.length && newPath > list.getChildAt(oldIdx).data.path) {
		    oldIdx++;
		}

		if (oldIdx >= list.childNodes.length || list.getChildAt(oldIdx).data.path !== newPath) {
		    list.insertChild(oldIdx, existingChildren[newPath]);
		}
	    }

	    let toRemove = [];
	    list.eachChild((child) => {
		if (!existingChildren[child.data.path]) {
		    toRemove.push(child);
		}
	    });
	    toRemove.forEach((child) => list.removeChild(child, true));

	    if (view.pathToSelect !== undefined) {
		let path = view.pathToSelect;
		delete view.pathToSelect;
		view.select(path, true);
	    }
	},

	onLoad: function(store, records, success) {
	    if (!success) {
		return;
	    }
	    let view = this.getView();
	    let root = view.getStore().getRoot();

	    records.sort((a, b) => a.id.localeCompare(b.id));

	    let list = root.findChild('id', 'datastores', false);
	    let getChildTextAt = i => list.getChildAt(i).data.text;
	    let existingChildren = {};
	    for (let i = 0, j = 0, length = records.length; i < length; i++) {
		let name = records[i].id;
		existingChildren[name] = true;

		while (name.localeCompare(getChildTextAt(j)) > 0 && (j+1) < list.childNodes.length) {
		    j++;
		}

		if (getChildTextAt(j).localeCompare(name) !== 0) {
		    list.insertChild(j, {
			text: name,
			path: `DataStore-${name}`,
			iconCls: 'fa fa-database',
			leaf: true,
		    });
		}
	    }

	    // remove entries which are not existing anymore
	    let toRemove = [];
	    list.eachChild(child => {
		if (!existingChildren[child.data.text] && !child.data.virtualEntry) {
		    toRemove.push(child);
		}
	    });
	    toRemove.forEach(child => list.removeChild(child, true));

	    if (view.pathToSelect !== undefined) {
		let path = view.pathToSelect;
		delete view.pathToSelect;
		view.select(path, true);
	    }
	},
    },

    listeners: {
	itemclick: function(tl, info) {
	    if (info.node.data.id === 'addbutton') {
		let me = this;
		Ext.create('PBS.DataStoreEdit', {
		    listeners: {
			destroy: () => me.rstore.reload(),
		    },
		}).show();
		return false;
	    }
	    return true;
	},
    },

    reloadTapeStore: function() {
	let me = this;
	me.tapeStore.load();
    },

    select: function(path, silent) {
	var me = this;
	if (me.rstore.isLoaded() && me.tapeStore.isLoaded()) {
	    if (silent) {
		me.suspendEvents(false);
	    }
	    var item = me.getStore().findRecord('path', path, 0, false, true, true);
	    me.setSelection(item);
	    if (silent) {
		me.resumeEvents(true);
	    }
	} else {
	    me.pathToSelect = path;
	}
    },

    animation: false,
    expanderOnly: true,
    expanderFirst: false,
    store: 'NavigationStore',
    ui: 'nav',
});