describe("Zotero.FileHandlers", () => {
	describe("open()", () => {
		var win;
		
		function clearPrefs() {
			Zotero.Prefs.clear('fileHandler.pdf');
			Zotero.Prefs.clear('fileHandler.epub');
			Zotero.Prefs.clear('fileHandler.snapshot');
			Zotero.Prefs.clear('openReaderInNewWindow');
		}
		
		before(async function () {
			clearPrefs();
			win = await loadZoteroPane();
		});

		afterEach(function () {
			clearPrefs();
			delete Zotero.FileHandlers._mockHandlers;
			for (let reader of Zotero.Reader._readers) {
				reader.close();
			}
		});

		after(async function () {
			win.close();
		});
		
		it("should open a PDF internally when no handler is set", async function () {
			let pdf = await importFileAttachment('wonderland_short.pdf');
			await Zotero.FileHandlers.open(pdf, {
				location: { pageIndex: 2 }
			});
			let reader = Zotero.Reader.getByTabID(win.Zotero_Tabs.selectedID);
			assert.ok(reader);
			
			let notifierPromise = waitForNotifierEvent('add', 'setting');
			await reader._waitForReader();
			await notifierPromise;
			
			// Check that the reader navigated to the correct page
			assert.equal(pdf.getAttachmentLastPageIndex(), 2);
		});

		it("should open a PDF in a new window when no handler is set and openInWindow is passed", async function () {
			let pdf = await importFileAttachment('wonderland_short.pdf');
			await Zotero.FileHandlers.open(pdf, {
				location: { pageIndex: 2 },
				openInWindow: true
			});
			assert.notOk(Zotero.Reader.getByTabID(win.Zotero_Tabs.selectedID));
			assert.isNotEmpty(Zotero.Reader.getWindowStates());
		});
		
		it("should use matching handler", async function () {
			let pdf = await importFileAttachment('wonderland_short.pdf');
			let wasRun = false;
			let readerOpenSpy = sinon.spy(Zotero.Reader, 'open');
			Zotero.FileHandlers._mockHandlers = {
				pdf: [
					{
						name: /mock/,
						async open() {
							wasRun = true;
						}
					}
				]
			};
			Zotero.Prefs.set('fileHandler.pdf', 'mock');
			
			await Zotero.FileHandlers.open(pdf);
			assert.isTrue(wasRun);
			assert.isFalse(readerOpenSpy.called);
			assert.notOk(Zotero.Reader.getByTabID(win.Zotero_Tabs.selectedID));
			assert.isEmpty(Zotero.Reader.getWindowStates());

			readerOpenSpy.restore();
		});

		it("should fall back to fallback handler when location is passed", async function () {
			let pdf = await importFileAttachment('wonderland_short.pdf');
			let wasRun = false;
			let readerOpenSpy = sinon.spy(Zotero.Reader, 'open');
			Zotero.FileHandlers._mockHandlers = {
				pdf: [
					{
						name: /mock/,
						fallback: true,
						async open(appPath) {
							assert.notOk(appPath); // appPath won't be set when called as fallback
							wasRun = true;
						}
					}
				]
			};

			// Set our custom handler to something nonexistent,
			// and stub the system handler to something nonexistent as well
			Zotero.Prefs.set('fileHandler.pdf', 'some nonexistent tool');
			let getSystemHandlerStub = sinon.stub(Zotero.FileHandlers, '_getSystemHandler');
			getSystemHandlerStub.returns('some other nonexistent tool');

			await Zotero.FileHandlers.open(pdf, { location: {} });
			assert.isTrue(wasRun);
			assert.isFalse(readerOpenSpy.called);
			assert.notOk(Zotero.Reader.getByTabID(win.Zotero_Tabs.selectedID));
			assert.isEmpty(Zotero.Reader.getWindowStates());

			readerOpenSpy.restore();
			getSystemHandlerStub.restore();
		});

		it("should fall back when handler is set to system and we can't retrieve the system handler", async function () {
			let pdf = await importFileAttachment('wonderland_short.pdf');
			let wasRun = false;
			let readerOpenSpy = sinon.spy(Zotero.Reader, 'open');
			let launchFileStub = sinon.stub(Zotero, 'launchFile');
			Zotero.FileHandlers._mockHandlers = {
				pdf: [
					{
						name: new RegExp(''),
						async open() {
							wasRun = true;
						}
					}
				]
			};

			// Set our custom handler to something nonexistent,
			// and stub the system handler to something nonexistent as well
			Zotero.Prefs.set('fileHandler.pdf', 'system');
			let getSystemHandlerStub = sinon.stub(Zotero.FileHandlers, '_getSystemHandler');
			getSystemHandlerStub.returns(false);

			await Zotero.FileHandlers.open(pdf, { location: {} });
			assert.isFalse(wasRun);
			assert.isFalse(readerOpenSpy.called);
			assert.isTrue(launchFileStub.called);
			assert.notOk(Zotero.Reader.getByTabID(win.Zotero_Tabs.selectedID));
			assert.isEmpty(Zotero.Reader.getWindowStates());

			readerOpenSpy.restore();
			launchFileStub.restore();
			getSystemHandlerStub.restore();
		});
	});
});