<?xml version="1.0"?>
<!--
    ***** BEGIN LICENSE BLOCK *****
    
    Copyright © 2009 Center for History and New Media
                     George Mason University, Fairfax, Virginia, USA
                     http://zotero.org
    
    This file is part of Zotero.
    
    Zotero is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    Zotero is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.
    
    You should have received a copy of the GNU Affero General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.
    
    ***** END LICENSE BLOCK *****
-->

<!DOCTYPE bindings SYSTEM "chrome://zotero/locale/zotero.dtd">

<bindings 	xmlns="http://www.mozilla.org/xbl"
			xmlns:xbl="http://www.mozilla.org/xbl"
			xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
	<binding id="related-box">
		<implementation>
			<!-- Modes are predefined settings groups for particular tasks -->
			<field name="_mode">"view"</field>
			<property name="mode" onget="return this._mode;">
				<setter>
				<![CDATA[
					this.clickable = false;
					this.editable = false;
					
					switch (val) {
						case 'view':
						case 'merge':
						case 'mergeedit':
							break;
						
						case 'edit':
							this.clickable = true;
							this.editable = true;
							//this.clickHandler = this.showEditor;
							//this.blurHandler = this.hideEditor;
							break;
						
						default:
							throw ("Invalid mode '" + val + "' in relatedbox.xml");
					}
					
					this._mode = val;
					document.getAnonymousNodes(this)[0].setAttribute('mode', val);
				]]>
				</setter>
			</property>
			
			<field name="itemRef"/>
			<property name="item" onget="return this.itemRef;">
				<setter>
					<![CDATA[
						this.itemRef = val;
						this.refresh();
					]]>
				</setter>
			</property>
			<property name="summary">
				<getter>
				<![CDATA[
					var r = "";
					
					if (this.item) {
						var keys = this.item.relatedItems;
						if (keys.length) {
							for (let key of keys) {
								let item = Zotero.Items.getByLibraryAndKey(this.item.libraryID, key);
								if (!item) {
									Zotero.debug(`Related item ${this.item.libraryID}/${key} not found `
										+ `for item ${this.item.libraryKey}`, 2);
									continue;
								}
								r = r + item.getDisplayTitle() + ", ";
							}
							r = r.substr(0,r.length-2);
						}
					}
					
					return r;
				]]>
				</getter>
			</property>
			
			<constructor>
			<![CDATA[
				this._notifierID = Zotero.Notifier.registerObserver(this, ['item'], 'relatedbox');
			]]>
			</constructor>
			
			<destructor>
			<![CDATA[
				Zotero.Notifier.unregisterObserver(this._notifierID);
			]]>
			</destructor>
			
			<!-- TODO: Asyncify -->
			<method name="notify">
				<parameter name="event"/>
				<parameter name="type"/>
				<parameter name="ids"/>
				<parameter name="extraData"/>
				<body><![CDATA[
					if (event != 'modify' || !this.item || !this.item.id) return;
					for (let i = 0; i < ids.length; i++) {
						let id = ids[i];
						if (id != this.item.id) {
							continue;
						}
						this.refresh();
						break;
					}
				]]></body>
			</method>
			
			<method name="refresh">
				<body><![CDATA[
					var addButton = this.id('addButton');
					addButton.hidden = !this.editable;
					
					var rows = this.id('relatedRows');
					while(rows.hasChildNodes())
						rows.removeChild(rows.firstChild);
					
					if (this.item) {
						var relatedKeys = this.item.relatedItems;
						for (var i = 0; i < relatedKeys.length; i++) {
							let key = relatedKeys[i];
							let relatedItem = Zotero.Items.getByLibraryAndKey(
								this.item.libraryID, key
							);
							if (!relatedItem) {
								Zotero.debug(`Related item ${this.item.libraryID}/${key} not found `
									+ `for item ${this.item.libraryKey}`, 2);
								continue;
							}
							let id = relatedItem.id;
							let icon = document.createElement("image");
							icon.className = "zotero-box-icon";
							icon.setAttribute('src', relatedItem.getImageSrc());
					
							var label = document.createElement("label");
							label.className = "zotero-box-label";
							label.setAttribute('value', relatedItem.getDisplayTitle());
							label.setAttribute('crop','end');
							label.setAttribute('flex','1');
							
							var box = document.createElement('box');
							box.setAttribute('onclick',
								"document.getBindingParent(this).showItem(" + id + ")");
							box.setAttribute('class','zotero-clicky');
							box.setAttribute('flex','1');
							box.appendChild(icon);
							box.appendChild(label);
							
							if (this.editable) {
								var remove = document.createElement("label");
								remove.setAttribute('value','-');
								remove.setAttribute('onclick',
									"document.getBindingParent(this).remove(" + id + ");");
								remove.setAttribute('class','zotero-clicky zotero-clicky-minus');
							}
							
							var row = document.createElement("row");
							row.appendChild(box);
							if (this.editable) {
								row.appendChild(remove);
							}
							rows.appendChild(row);
						}
						this.updateCount(rows.childNodes.length);
					}
				]]></body>
			</method>
			<method name="add">
				<body><![CDATA[
					return Zotero.spawn(function* () {
						var io = {dataIn: null, dataOut: null};
						
						window.openDialog('chrome://zotero/content/selectItemsDialog.xul', '',
								'chrome,dialog=no,modal,centerscreen,resizable=yes', io);
						
						if (!io.dataOut || !io.dataOut.length) {
							return;
						}
						var relItems = yield Zotero.Items.getAsync(io.dataOut);
						if (!relItems.length) {
							return;
						}
						
						if (relItems[0].libraryID != this.item.libraryID) {
							// FIXME
							var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
													.getService(Components.interfaces.nsIPromptService);
							ps.alert(null, "", "You cannot relate items in different libraries.");
							return;
						}
						yield Zotero.DB.executeTransaction(function* () {
							for (let relItem of relItems) {
								if (this.item.addRelatedItem(relItem)) {
									yield this.item.save({
										skipDateModifiedUpdate: true
									});
								}
								if (relItem.addRelatedItem(this.item)) {
									yield relItem.save({
										skipDateModifiedUpdate: true
									});
								}
							}
						}.bind(this));
					}, this);
				]]></body>
			</method>
			<method name="remove">
				<parameter name="id"/>
				<body><![CDATA[
					return Zotero.spawn(function* () {
						var item = yield Zotero.Items.getAsync(id);
						if (item) {
							yield Zotero.DB.executeTransaction(function* () {
								if (this.item.removeRelatedItem(item)) {
									yield this.item.save({
										skipDateModifiedUpdate: true
									});
								}
								if (item.removeRelatedItem(this.item)) {
									yield item.save({
										skipDateModifiedUpdate: true
									});
								}
							}.bind(this));
						}
					}, this);
				]]></body>
			</method>
			<method name="showItem">
				<parameter name="id"/>
				<body>
					<![CDATA[
						if(id)
						{
							var p;
							if(window.ZoteroPane_Local)
							{
								p = window.ZoteroPane_Local;
							}
							else
							{
								var win;
														
								if(window.opener && window.opener.ZoteroPane)
								{
									win = window.opener;
								}
								else
								{
									var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
														.getService(Components.interfaces.nsIWindowMediator);
									win = wm.getMostRecentWindow('navigator:browser');
									if(!win)
										return;
								}
								
								p = win.ZoteroPane;
							}
								
							p.selectItem(id);
						}
					]]>
				</body>
			</method>
			<method name="updateCount">
				<parameter name="count"/>
				<body>
					<![CDATA[
						if (count == null) {
							var count = this.item.relatedItems.length;
						}
						
						var str = 'pane.item.related.count.';
						switch (count){
							case 0:
								str += 'zero';
								break;
							case 1:
								str += 'singular';
								break;
							default:
								str += 'plural';
								break;
						}
						this.id('relatedNum').value = Zotero.getString(str, [count]);
					]]>
				</body>
			</method>
			<method name="id">
				<parameter name="id"/>
				<body>
					<![CDATA[
						return document.getAnonymousNodes(this)[0].getElementsByAttribute('id',id)[0];
					]]>
				</body>
			</method>
		</implementation>
		<content>
			<xul:vbox xbl:inherits="flex" class="zotero-box">
				<xul:hbox align="center">
					<xul:label id="relatedNum"/>
					<xul:button id="addButton" label="&zotero.item.add;"
						oncommand="this.parentNode.parentNode.parentNode.add();"/>
				</xul:hbox>
				<xul:grid flex="1">
					<xul:columns>
						<xul:column flex="1"/>
						<xul:column/>
					</xul:columns>
					<xul:rows id="relatedRows"/>
				</xul:grid>
			</xul:vbox>
		</content>
	</binding>
</bindings>
