/**
 * EGroupware eTemplate2 - Class which contains a the data model for nextmatch widgets
 *
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
 * @package etemplate
 * @subpackage api
 * @link http://www.egroupware.org
 * @author Andreas Stöckel
 * @copyright Stylite 2012
 * @version $Id$
 */

"use strict";

/*egw:uses
	et2_core_common;
	et2_core_inheritance;

	et2_dataview_view_row;
	et2_dataview_controller;
	et2_dataview_interfaces;

	et2_extension_nextmatch_actions; // Contains nm_action

	egw_data;
*/

/**
 * @augments et2_dataview_controller
 */
var et2_nextmatch_controller = et2_dataview_controller.extend(et2_IDataProvider, 
{
	/**
	 * Initializes the nextmatch controller.
	 *
	 * @param _parentController is the parent nextmatch controller instance
	 * @param _egw is the api instance
	 * @param _execId is the execId of the etemplate
	 * @param _widget is the nextmatch-widget we are fetching data for.
	 * @param _grid is the grid the grid controller will be controlling
	 * @param _rowProvider is the nextmatch row provider instance.
	 * @param _objectManager is the parent object manager (if null, the object
	 * manager) will be created using
	 * @param _actionLinks contains the action links
	 * @param _actions contains the actions, may be null if an object manager
	 * is given.
	 * @memberOf et2_nextmatch_controller
	 */
	init: function (_parentController, _egw, _execId, _widget, _parentId,
			_grid, _rowProvider, _actionLinks, _objectManager, _actions) {

		// Copy the egw reference
		this.egw = _egw;

		// Keep a reference to the widget
		this._widget = _widget;

		// Initialize the action and the object manager
		if (!_objectManager)
		{
			this._initActions(_actions);
		}
		else
		{
			this._actionManager = null;
			this._objectManager = _objectManager;
		}
		// Add our selection callback to selection manager
		var self = this;
		this._objectManager.setSelectedCallback = function() {self._selectCallback.apply(self,[this,arguments]);};

		// Call the parent et2_dataview_controller constructor
		this._super(_parentController, _grid, this, this._rowCallback,
			this._linkCallback, this, this._objectManager);

		// Copy the given parameters
		this._actionLinks = _actionLinks;
		this._execId = _execId;
		this._widgetId = _widget.id;
		this._parentId = _parentId;
		this._rowProvider = _rowProvider;

		// We start with no filters
		this._filters = {};

		// Directly use the API-Implementation of dataRegisterUID and
		// dataUnregisterUID
		this.dataUnregisterUID = _egw.dataUnregisterUID;

	},

	destroy: function () {
		// If the actionManager variable is set, the object- and actionManager
		// were created by this instance -- clear them
		if (this._actionManager)
		{
			this._objectManager.remove();
			this._actionManager.remove();
		}

		this._super();
	},

	/**
	 * Updates the filter instance.
	 */
	setFilters: function (_filters) {
		// Update the filters, reset the "lastModification"
		this._filters = _filters;
		this._lastModification = null;
	},

	getObjectManager: function () {
		return this._objectManager;
	},


	/** -- PRIVATE FUNCTIONS -- **/

	/**
	 * Initializes the action and the object manager.
	 */
	_initActions: function (_actions) {
		// Generate a uid for the action and object manager
		var uid = this.egw.uid();

		if(_actions == null) _actions = [];

		// Initialize the action manager and add some actions to it
		var gam = egw_getActionManager(this.egw.appName);
		this._actionManager = gam.addAction("actionManager", uid);
		this._actionManager.updateActions(_actions);
		var data = this._actionManager.data;
		if (data == 'undefined' || !data)
		{
			data = {};
		}
		data.nextmatch = this._widget;
		this._actionManager.set_data(data);

		// Set the default execute handler
		var self = this;
		this._actionManager.setDefaultExecute(function (_action, _senders, _target) {
			// Get the selected ids descriptor object
			var ids = self._selectionMgr.getSelected();

			// Pass a reference to the actual widget
			if (typeof _action.data == 'undefined' || !_action.data) _action.data = {};
			_action.data.nextmatch = self._widget;

			// Call the nm_action function with the ids
			nm_action(_action, _senders, _target, ids);
		});

		// Initialize the object manager
		var gom = egw_getObjectManager(this.egw.appName);
		this._objectManager = gom.addObject(
				new egwActionObjectManager(uid, this._actionManager));
		this._objectManager.flags = this._objectManager.flags
				| EGW_AO_FLAG_DEFAULT_FOCUS | EGW_AO_FLAG_IS_CONTAINER;
	},

	/**
	 * Overwrites the inherited _destroyCallback function in order to be able
	 * to free the "rowWidget".
	 */
	_destroyCallback: function (_row) {
		// Destroy any widget associated to the row
		if (this.entry.widget)
		{
			this.entry.widget.free();
			this.entry.widget = null;
		}

		// Call the inherited function
		this._super.call(this, arguments);
	},

	/**
	 * Creates the actual data row.
	 *
	 * @param _data is an array containing the row data
	 * @param _tr is the tr into which the data will be inserted
	 * @param _idx is the index of the row
	 * @param _entry is the internal row datastructure of the controller, in
	 * this special case used to store the rowWidget reference, so that it can
	 * be properly freed.
	 */
	_rowCallback: function (_data, _tr, _idx, _entry) {
		// Let the row provider fill in the data row -- store the returned
		// rowWidget inside the _entry
		_entry.widget = this._rowProvider.getDataRow(
			{ "content": _data }, _tr, _idx, this);
	},

	/**
	 * Returns the names of action links for a given data row -- currently these are
	 * always the same links, as we controll enabled/disabled over the row
	 * classes, unless the row UID is "", then it's an 'empty' row.
	 *
	 * The empty row placeholder can still have actions, but nothing that requires
	 * an actual UID.  
	 *
	 * @TODO: Currently empty row is just add, need to actually filter somehow.  Here
	 * 	might not be the right place.
	 *
	 * @param _data Object The data for the row
	 * @param _idx int The row index
	 * @param _uid String The row's ID
	 *
	 * @return Array List of action names that valid for the row
	 */
	_linkCallback: function (_data, _idx, _uid) {
		if(_uid.trim() != "")
		{
			return this._actionLinks;
		}

		// No UID, so return a filtered list of actions that doesn't need a UID
		var links = [];
		try {
			links = this._widget.options.settings.placeholder_actions;
		} catch (e) {
		}

		return links;
	},


	/**
	 * Overridden from the parent to also process any additional data that
	 * the data source adds, such as readonlys and additonal content.
	 * For example, non-numeric IDs in rows are added to the content manager
	 */
	_fetchCallback: function (_response) {
		var nm = this.self._widget;

		// Readonlys
		// Other stuff
		for(var i in _response.rows)
		{
			if(jQuery.isNumeric(i)) continue;
			if(i == 'sel_options')
			{
				var mgr = nm.getArrayMgr(i);
				for(var id in _response.rows.sel_options)
				{
					mgr.data[id] = _response.rows.sel_options[id];
					var select = nm.getWidgetById(id);
					if(select && select.set_select_options)
					{
						select.set_select_options(_response.rows.sel_options[id]);
					}
				}
			}
			else
			{
				var mgr = nm.getArrayMgr('content');
				mgr.data[i] = _response.rows[i];
			}
		}

		// Call the inherited function
		this._super.apply(this, arguments);
	},

	/**
	 * Execute the select callback when the row selection changes
	 */
	_selectCallback: function(action,senders)
	{
		if(typeof senders == "undefined")
		{
			senders = [];
		}
		if(!this._widget) return;
		this._widget.onselect.call(this._widget, action,senders);
	},

	/** -- Implementation of et2_IDataProvider -- **/


	dataFetch: function (_queriedRange, _callback, _context) {

		// Merge the parent id into the _queriedRange if it is set
		if (this._parentId !== null)
		{
			_queriedRange["parent_id"] = this._parentId;
		}

		// Pass the fetch call to the API, multiplex the data about the
		// nextmatch instance into the call.
		this.egw.dataFetch(
				this._execId,
				_queriedRange,
				this._filters,
				this._widgetId,
				_callback,
				_context);
	},

	dataRegisterUID: function (_uid, _callback, _context) {
		this.egw.dataRegisterUID(_uid, _callback, _context, this._execId,
				this._widgetId);
	},

	dataUnregisterUID: function () {
		// Overwritten in the constructor
	}

});