"use strict";

describe("ItemTreeRow", function () {
	var win;
	var ItemTreeRow;
	var ZoteroItemTreeRow;
	var FileItemTreeRow;
	var AnnotationItemTreeRow;
	var CollectionItemTreeRow;
	var SearchItemTreeRow;

	before(async function () {
		win = await loadZoteroPane();
		({
			ItemTreeRow,
			ZoteroItemTreeRow,
			FileItemTreeRow,
			AnnotationItemTreeRow,
			CollectionItemTreeRow,
			SearchItemTreeRow,
		} = win.require('zotero/itemTreeRow'));
		await selectLibrary(win);
	});

	after(function () {
		win.close();
	});

	it("should create row subclasses via factory", async function () {
		let item = await createDataObject('item');
		let attachment = await importFileAttachment('test.pdf', { parentItemID: item.id });
		let annotation = await createAnnotation('highlight', attachment);
		let collection = await createDataObject('collection');
		let search = await createDataObject('search');

		assert.instanceOf(ItemTreeRow.create(item, 0, false), ZoteroItemTreeRow);
		assert.instanceOf(ItemTreeRow.create(attachment, 0, false), FileItemTreeRow);
		assert.instanceOf(ItemTreeRow.create(annotation, 0, false), AnnotationItemTreeRow);
		assert.instanceOf(ItemTreeRow.create(annotation, 0, false), ZoteroItemTreeRow);
		assert.instanceOf(ItemTreeRow.create(collection, 0, false), CollectionItemTreeRow);
		assert.instanceOf(ItemTreeRow.create(search, 0, false), SearchItemTreeRow);
	});

	it("should provide container and child behavior for regular items and file attachments", async function () {
		let item = await createDataObject('item');
		let note = await createDataObject('item', { itemType: 'note', parentID: item.id });
		let attachment = await importFileAttachment('test.pdf', { parentItemID: item.id });
		let annotation = await createAnnotation('highlight', attachment);

		let itemRow = ItemTreeRow.create(item, 0, false);
		assert.isTrue(itemRow.isContainer());
		assert.isFalse(itemRow.isContainerOpen());
		assert.isFalse(itemRow.isContainerEmpty({
			searchMode: false,
			searchItemIDs: new Set(),
			includeTrashed: false,
		}));
		assert.sameMembers(
			itemRow.getChildItems({ includeTrashed: false }).map(x => x.id),
			[note.id, attachment.id]
		);

		let attachmentRow = ItemTreeRow.create(attachment, 1, false);
		assert.isTrue(attachmentRow.isContainer());
		assert.isFalse(attachmentRow.isContainerOpen());
		assert.sameMembers(
			attachmentRow.getChildItems({
				searchMode: false,
				searchItemIDs: new Set(),
				includeTrashed: false,
			}).map(x => x.id),
			[annotation.id]
		);

		let annotationRow = ItemTreeRow.create(annotation, 2, false);
		assert.isFalse(annotationRow.isContainer());
	});

	it("should expose attachment-state behavior by row type", async function () {
		let item = await createDataObject('item');
		let childAttachment = await importFileAttachment('test.pdf', { parentItemID: item.id });
		let topLevelAttachment = await importFileAttachment('test.pdf');
		let annotation = await createAnnotation('highlight', topLevelAttachment);
		let note = await createDataObject('item', { itemType: 'note' });
		let collection = await createDataObject('collection');
		let search = await createDataObject('search');

		let itemRow = ItemTreeRow.create(item, 0, false);
		let childAttachmentRow = ItemTreeRow.create(childAttachment, 1, false);
		let topLevelAttachmentRow = ItemTreeRow.create(topLevelAttachment, 0, false);
		let annotationRow = ItemTreeRow.create(annotation, 1, false);
		let noteRow = ItemTreeRow.create(note, 0, false);
		let collectionRow = ItemTreeRow.create(collection, 0, false);
		let searchRow = ItemTreeRow.create(search, 0, false);

		assert.ok(itemRow.getBestAttachmentState()?.then);
		assert.notOk(childAttachmentRow.getBestAttachmentState());
		assert.ok(topLevelAttachmentRow.getBestAttachmentState()?.then);
		assert.notOk(annotationRow.getBestAttachmentState());
		assert.notOk(noteRow.getBestAttachmentState());
		assert.notOk(collectionRow.getBestAttachmentState());
		assert.notOk(searchRow.getBestAttachmentState());
	});

	it("should return localized type labels for all row types", async function () {
		let item = await createDataObject('item', { itemType: 'book' });
		let attachment = await importFileAttachment('test.pdf', { parentItemID: item.id });
		let annotation = await createAnnotation('highlight', attachment);
		let collection = await createDataObject('collection');
		let search = await createDataObject('search');

		let itemRow = ItemTreeRow.create(item, 0, false);
		let attachmentRow = ItemTreeRow.create(attachment, 1, false);
		let annotationRow = ItemTreeRow.create(annotation, 2, false);
		let collectionRow = ItemTreeRow.create(collection, 0, false);
		let searchRow = ItemTreeRow.create(search, 0, false);

		assert.equal(itemRow.getTypeLabel(), Zotero.ItemTypes.getLocalizedString(item.itemTypeID));
		assert.equal(attachmentRow.getTypeLabel(), Zotero.ItemTypes.getLocalizedString(attachment.itemTypeID));
		assert.equal(annotationRow.getTypeLabel(), Zotero.ItemTypes.getLocalizedString(annotation.itemTypeID));
		assert.equal(collectionRow.getTypeLabel(), Zotero.getString('search-conditions-collection'));
		assert.equal(searchRow.getTypeLabel(), Zotero.getString('search-conditions-savedSearch'));
	});

	it("should return filename as display title for file attachment when pref is enabled", async function () {
		let pref = Zotero.Prefs.get('showAttachmentFilenames');
		let item = await createDataObject('item');
		let attachment = await importFileAttachment('test.pdf', { parentItemID: item.id });
		attachment.setField('title', 'Custom Attachment Title');
		await attachment.saveTx();

		try {
			Zotero.Prefs.set('showAttachmentFilenames', false);
			let withoutPref = ItemTreeRow.create(attachment, 1, false);
			assert.equal(withoutPref.getDisplayTitle(), attachment.getDisplayTitle());

			Zotero.Prefs.set('showAttachmentFilenames', true);
			let withPref = ItemTreeRow.create(attachment, 1, false);
			assert.notEqual(withPref.getDisplayTitle(), attachment.getDisplayTitle());
			assert.equal(withPref.getDisplayTitle(), attachment.attachmentFilename);
		}
		finally {
			Zotero.Prefs.set('showAttachmentFilenames', pref);
		}
	});

	it("should render annotation row content with title and comment cells", async function () {
		let item = await createDataObject('item');
		let attachment = await importFileAttachment('test.pdf', { parentItemID: item.id });
		let annotation = await createAnnotation('highlight', attachment, {
			comment: 'Annotation comment',
		});

		let row = ItemTreeRow.create(annotation, 2, false);
		let div = win.document.createElement('div');
		let columns = [{ dataKey: 'title', className: 'title' }];
		let calls = {
			renderCell: 0,
		};

		let renderCtx = {
			firstColumn: columns[0],
			renderCell: () => {
				calls.renderCell++;
				let span = win.document.createElement('span');
				span.className = 'cell title';
				let text = win.document.createElement('span');
				text.className = 'cell-text';
				span.append(text);
				return span;
			},
		};

		row.renderRow(div, 0, columns, {}, renderCtx);

		assert.equal(row.type, 'annotation');
		assert.isTrue(div.classList.contains('annotation-row'));
		assert.isAbove(calls.renderCell, 0);
		assert.exists(div.querySelector('.annotation-comment'));
	});
});
