/*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: ZAPL 1.1
 * 
 * The contents of this file are subject to the Zimbra AJAX Public
 * License Version 1.1 ("License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.zimbra.com/license
 * 
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is: Zimbra AJAX Toolkit.
 * 
 * The Initial Developer of the Original Code is Zimbra, Inc.
 * Portions created by Zimbra are Copyright (C) 2005 Zimbra, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK *****
 */

//
// Constructor
//

/**
 * Constructs a control that shows two lists of items and allows the user
 * to move items between the two lists.
 *
 * @param parent    The parent container for this control.
 * @param className (optional) The CSS class for this control. Default
 *					value is "DwtAddRemove".
 * @param posStyle  (optional) The position style of this control.
 */
function DwtAddRemove(parent, className, posStyle, listClassName) {
	if (arguments.length == 0) return;
	className = className || "DwtAddRemove";
	posStyle = posStyle || DwtControl.STATIC_STYLE;
	DwtComposite.call(this, parent, className, posStyle);
	this._createHTML(listClassName);
	this.isUpdating = false;
}

DwtAddRemove.prototype = new DwtComposite;
DwtAddRemove.prototype.constructor = DwtAddRemove;

DwtAddRemove.prototype.toString = function() {
	return "DwtAddRemove";
}

//
// Constants
//

/***
DwtAddRemove.ORIENTATION_HORIZONTAL = 0;
DwtAddRemove.ORIENTATION_VERTICAL = 1;

DwtAddRemove.SELECTION_SINGLE = 0;
DwtAddRemove.SELECTION_MULTIPLE = 1;
/***/

//
// Data
//

/***
DwtAddRemove.prototype._orientation = DwtAddRemove.ORIENTATION_HORIZONTAL;
DwtAddRemove.prototype._selection = DwtAddRemove.SELECTION_SINGLE;
/***/

// visual controls
DwtAddRemove.prototype._sourceList;
DwtAddRemove.prototype._addAllButton;
DwtAddRemove.prototype._addButton;
DwtAddRemove.prototype._removeButton;
DwtAddRemove.prototype._removeAllButton;
DwtAddRemove.prototype._targetList;

//
// Public methods
//

// listeners

DwtAddRemove.prototype.addStateChangeListener = function(listener) {
	this._targetList.addStateChangeListener(listener);
}

DwtAddRemove.prototype.removeStateChangeListener = function(listener) {
	this._targetList.removeStateChangeListener(listener);
}

// properties

/***
DwtAddRemove.prototype.setOrientation = function(orientation) {
	this._orientation = orientation;
}
DwtAddRemove.prototype.getOrientation = function() {
	return this._orientation;
}
DwtAddRemove.prototype.isHorizontal = function() {
	return this._orientation === DwtAddRemove.ORIENTATION_HORIZONTAL;
}
DwtAddRemove.prototype.isVertical = function() {
	return this._orientation === DwtAddRemove.ORIENTATION_VERTICAL;
}

DwtAddRemove.prototype.setSelection = function(selection) {
	this._selection = selection;
}
DwtAddRemove.prototype.getSelection = function() {
	return this._selection;
}
DwtAddRemove.prototype.isSingleSelect = function() {
	return this._selection === DwtAddRemove.SELECTION_SINGLE;
}
DwtAddRemove.prototype.isMultiSelect = function() {
	return this._selection === DwtAddRemove.SELECTION_MULTIPLE;
}
/***/

// public methods

DwtAddRemove.prototype.getSourceItems = function() {
	var list = this._sourceList.getList();
	var items = list ? list.clone().getArray() : [];
	return items ? items : [];
}
DwtAddRemove.prototype.setSourceItems = function(items) {
	this.removeAllSourceItems();
	this.addSourceItems(items);
}
DwtAddRemove.prototype.removeAllSourceItems = function() {
	// DwtListView#set calls removeAll and setUI
	//this._sourceList.removeAll();
	var list = new AjxVector();
	this._sourceList.set(list);
		
	this._addAllButton.setEnabled(false);
	this._addButton.setEnabled(false);
}
DwtAddRemove.prototype.removeSourceItem = function(item) {
	if (Array_contains(this.getSourceItems(), item)) {
		this._sourceList.removeItem(item);
		this._addAllButton.setEnabled(this.getSourceItems().length > 0);
		this._addButton.setEnabled(this._sourceList.getSelectionCount() > 0);
	}
}

DwtAddRemove.prototype.removeSourceItems = function(items) {
	for (var i = 0; i < items.length; i++) {
		this.removeSourceItem(items[i]);
	}
}

DwtAddRemove.prototype.addSourceItems = function(items) {
	for (var i = 0; i < items.length; i++) {
		this.addSourceItem(items[i]);
	}
}
DwtAddRemove.prototype.addSourceItem = function(item) {
	if (!Array_contains(this.getSourceItems(), item)) {
		this._sourceList.addItem(item);
		this._addAllButton.setEnabled(true);
	}
}

DwtAddRemove.prototype.getTargetItems = function() {
	var list = this._targetList.getList();
	var items = list ? list.clone().getArray() : [];
	return items ? items : [];
}
DwtAddRemove.prototype.setTargetItems = function(items) {
	this.removeAllTargetItems(false);
	this.addTargetItems(items);
}
DwtAddRemove.prototype.removeAllTargetItems = function(skipNotify) {
	// DwtListView#set calls removeAll and setUI
	//this._targetList.removeAll(skipNotify);
	var list = new AjxVector();
	this._targetList.set(list);
		
	this._removeButton.setEnabled(false);
	this._removeAllButton.setEnabled(false);
}
DwtAddRemove.prototype.removeTargetItem = function(item, skipNotify) {
	if (Array_contains(this.getTargetItems(), item)) {
		this._targetList.removeItem(item, skipNotify);
		this._removeButton.setEnabled(this._targetList.getSelectionCount() > 0);
		this._removeAllButton.setEnabled(this.getTargetItems().length > 0);
	}
}
DwtAddRemove.prototype.addTargetItems = function(items, skipNotify) {
	for (var i = 0; i < items.length; i++) {
		skipNotify = skipNotify || i < items.length - 1;
		this.addTargetItem(items[i], skipNotify);
	}
}
DwtAddRemove.prototype.addTargetItem = function(item, skipNotify) {
	if (!Array_contains(this.getTargetItems(), item)) {
		this._targetList.addItem(item, null, skipNotify);
		this._removeAllButton.setEnabled(true);
	}
}

// util methods

Array_contains = function(array, object) {
	for (var i = 0; i < array.length; i++) {
		if (array[i] === object) {
			return true;
		}
	}
	return false;
}

// DwtComponent methods

DwtAddRemove.prototype.setEnabled = function(enabled) {
	// NOTE: DwtComposite doesn't propagate enabled to its children!
	//DwtComposite.prototype.setEnabled.call(this, enabled);
	this._sourceList.setEnabled(enabled);
	this._addAllButton.setEnabled(enabled ? this.getSourceItems().length > 0 : false);
	this._addButton.setEnabled(enabled ? this._sourceList.getSelectionCount() > 0 : false);
	this._removeButton.setEnabled(enabled ? this._targetList.getSelectionCount() > 0 : false);
	this._removeAllButton.setEnabled(enabled ? this.getTargetItems().length > 0 : false);
	this._targetList.setEnabled(enabled);
}

//
// Protected methods
//

/** @protected */
DwtAddRemove.prototype._sourceListListener = function(event) {
	var count = this._sourceList.getSelectionCount();
	this._addButton.setEnabled(count > 0);
}
/** @protected */
DwtAddRemove.prototype._addAllButtonListener = function(event) {
	this.isUpdating = true;
	var items = this.getSourceItems();
	//this.addTargetItems(items);
	for (var i = 0; i < items.length; i++) {
		var skipNotify = i < items.length - 1;
		this.addTargetItem(items[i], skipNotify);
	}
	this.removeAllSourceItems();
}
/** @protected */
DwtAddRemove.prototype._addButtonListener = function(event) {
	this.isUpdating = true;
	var itemDivs = this._sourceList.getSelectedItems().clone().getArray();
	for (var i = 0; i < itemDivs.length; i++) {
		var item = this._sourceList.getItemFromElement(itemDivs[i]);
		this.removeSourceItem(item);
		var skipNotify = i < itemDivs.length - 1;
		this.addTargetItem(item, skipNotify);
	}
}
/** @protected */
DwtAddRemove.prototype._removeButtonListener = function(event) {
	this.isUpdating = true;
	var itemDivs = this._targetList.getSelectedItems().clone().getArray();
	for (var i = 0; i < itemDivs.length; i++) {
		var item = this._targetList.getItemFromElement(itemDivs[i]);
		var skipNotify = i < itemDivs.length - 1;
		this.removeTargetItem(item, skipNotify);
		this.addSourceItem(item);
	}
}
/** @protected */
DwtAddRemove.prototype._removeAllButtonListener = function(event) {
	this.isUpdating = true;
	var items = this.getTargetItems();
	for (var i = 0; i < items.length; i++) {
		this.addSourceItem(items[i]);
	}
	this.removeAllTargetItems();
}
/** @protected */
DwtAddRemove.prototype._targetListListener = function(event) {
	var count = this._targetList.getSelectionCount();
	this._removeButton.setEnabled(count > 0);
}

/** @protected */
DwtAddRemove.prototype._createHTML = function(listClassName) {

	// create unique identifiers
	var thisId = this.getHtmlElement().id;
	var sourceDivId = thisId+"_source";
	var controlsDivId = thisId+"_controls";
	var targetDivId = thisId+"_target";

	// create html content
	var div = this.getHtmlElement();
	var width = 100; // REVISIT

	var document = this.getDocument();
	var table = document.createElement("TABLE");
	table.border = 0;
	table.cellPadding = 0;
	table.cellSpacing = 4;
	
	var row = table.insertRow(table.rows.length);

	var sourceDiv = row.insertCell(row.cells.length);
	sourceDiv.id = sourceDivId;
	sourceDiv.width = width; // REVISIT
	
	var controlsDiv = row.insertCell(row.cells.length);
	controlsDiv.id = controlsDivId;
	controlsDiv.align = "center";
	if (AjxEnv.isIE) {
		controlsDiv.style.paddingRight = "4px";
	}
	
	var targetDiv = row.insertCell(row.cells.length);
	targetDiv.id = targetDivId;
	targetDiv.width = width; // REVISIT

	div.appendChild(table);
		
	// create controls
	// REVISIT: replace with light-weight list boxes?
	this._sourceList = new DwtAddRemoveListView(this, listClassName);
	this._addAllButton = new DwtButton(this);
	this._addButton = new DwtButton(this);
	this._removeButton = new DwtButton(this);
	this._removeAllButton = new DwtButton(this);
	this._targetList = new DwtAddRemoveListView(this, listClassName);

	// initialize controls
	this._sourceList._setNoResultsHtml = new Function();
	this._sourceList.addSelectionListener(new AjxListener(this, this._sourceListListener));

	this._addAllButton.setText(DwtMsg.addAll);
	this._addAllButton.setEnabled(false);
	this._addAllButton.addSelectionListener(new AjxListener(this, this._addAllButtonListener));

	this._addButton.setText(DwtMsg.add);
	this._addButton.setEnabled(false);
	this._addButton.addSelectionListener(new AjxListener(this, this._addButtonListener));
	
	this._removeButton.setText(DwtMsg.remove);
	this._removeButton.setEnabled(false);
	this._removeButton.addSelectionListener(new AjxListener(this, this._removeButtonListener));

	this._removeAllButton.setText(DwtMsg.removeAll);
	this._removeAllButton.setEnabled(false);
	this._removeAllButton.addSelectionListener(new AjxListener(this, this._removeAllButtonListener));

	this._targetList._setNoResultsHtml = new Function();
	this._targetList.addSelectionListener(new AjxListener(this, this._targetListListener));

	// insert controls into html
	sourceDiv.appendChild(this._sourceList.getHtmlElement());
	
	controlsDiv.appendChild(this._addAllButton.getHtmlElement());
	controlsDiv.appendChild(document.createElement("BR"));
	controlsDiv.appendChild(this._addButton.getHtmlElement());
	controlsDiv.appendChild(document.createElement("BR"));
	controlsDiv.appendChild(this._removeButton.getHtmlElement());
	controlsDiv.appendChild(document.createElement("BR"));
	controlsDiv.appendChild(this._removeAllButton.getHtmlElement());
	
	targetDiv.appendChild(this._targetList.getHtmlElement());
	
} // DwtAddRemove#_createHTML

function DwtAddRemoveListView(parent, className) {
	className = className || "DwtAddRemoveListView";
	DwtListView.call(this, parent, className);
}
DwtAddRemoveListView.prototype = new DwtListView;
DwtAddRemoveListView.prototype.constructor = DwtAddRemoveListView;

DwtAddRemoveListView.prototype._createItemHtml = function(item, now, isDnDIcon) {
	var document = this.getDocument();
	var div = document.createElement("DIV");
	div.id = Dwt.getNextId();
	div._styleClass = 
		"Row "+
		"DwtAddRemoveListViewRow";
	div._selectedStyleClass = 
		"Row-"+DwtCssStyle.SELECTED+" "+
		"DwtAddRemoveListViewRow";
	div._selectedDisabledStyleClass = 
		"Row-"+DwtCssStyle.SELECTED+"-"+DwtCssStyle.DISABLED+" "+
		"DwtAddRemoveListViewRow";
	div.className = div._styleClass;
	if( typeof (item) == "object") {
		div.innerHTML = AjxStringUtil.htmlEncode(item.toString());
	} else {
		div.innerHTML = AjxStringUtil.htmlEncode(String(item));
	}
	this.associateItemWithElement(item, div, DwtListView.TYPE_LIST_ITEM);
	return div;
}

DwtAddRemoveListView.prototype._mouseUpAction =
function(ev, div) {
	if (ev.button == DwtMouseEvent.LEFT) {
		if (this._evtMgr.isListenerRegistered(DwtEvent.SELECTION)) {
			this._selEv.field = ev.target.id.substring(0, 3);
			this._evtMgr.notifyListeners(DwtEvent.SELECTION, this._selEv);
		}
	}
	return true;
}

