/**
 * A notifications list organized and separated by dates
 *
 * @class
 * @extends OO.ui.Widget
 * @mixes OO.ui.mixin.PendingElement
 *
 * @constructor
 * @param {mw.echo.Controller} controller Echo controller
 * @param {mw.echo.dm.ModelManager} modelManager Model manager
 * @param {Object} [config={}]
 * @param {boolean} [config.animateSorting=false] Animate the sorting of items
 * @param {jQuery} [config.$overlay] An overlay for the popup menus
 */
mw.echo.ui.DatedNotificationsWidget = function MwEchoUiDatedNotificationsListWidget( controller, modelManager, config ) {
	config = config || {};

	// Parent constructor
	mw.echo.ui.DatedNotificationsWidget.super.call( this, config );
	// Mixin constructors
	OO.ui.mixin.PendingElement.call( this, config );

	this.manager = modelManager;
	this.controller = controller;
	this.models = {};

	this.$overlay = config.$overlay || this.$element;
	this.animateSorting = !!config.animateSorting;

	this.listWidget = new mw.echo.ui.SortedListWidget(
		// Sorting callback
		( ( a, b ) => {
			// Reverse sorting
			if ( b.getTimestamp() < a.getTimestamp() ) {
				return -1;
			} else if ( b.getTimestamp() > a.getTimestamp() ) {
				return 1;
			}
		} ),
		// Config
		{
			classes: [ 'mw-echo-ui-datedNotificationsWidget-group' ],
			$overlay: this.$overlay,
			animated: false
		}
	);

	// Events
	this.manager.connect( this, {
		update: 'populateFromModel',
		discard: 'onManagerDiscardModel'
	} );

	this.$element
		.addClass( 'mw-echo-ui-datedNotificationsWidget' )
		.append( this.listWidget.$element );

	// Initialization
	this.populateFromModel();
};
/* Initialization */

OO.inheritClass( mw.echo.ui.DatedNotificationsWidget, OO.ui.Widget );
OO.mixinClass( mw.echo.ui.DatedNotificationsWidget, OO.ui.mixin.PendingElement );

mw.echo.ui.DatedNotificationsWidget.prototype.onManagerDiscardModel = function ( modelId ) {
	const model = this.models[ modelId ],
		list = this.getList();

	if ( model ) {
		const group = list.getItemFromId( model.getName() );
		list.removeItems( [ group ] );
	}
};
/**
 * Respond to model removing source group
 *
 * @param {string} source Symbolic name of the source group
 */
mw.echo.ui.DatedNotificationsWidget.prototype.onModelRemoveSource = function ( source ) {
	const list = this.getList(),
		group = list.getItemFromId( source );

	list.removeItems( [ group ] );
};

/**
 * Respond to model manager update event.
 * This event means we are repopulating the entire list and the
 * associated models within it.
 *
 * @param {Object} models List models, indexed by ID
 */
mw.echo.ui.DatedNotificationsWidget.prototype.populateFromModel = function ( models ) {
	const groupWidgets = [];

	// Detach all attached models
	for ( const modelId in this.models ) {
		this.detachModel( modelId );
	}

	for ( const model in models ) {
		// Create SubGroup widgets
		const subgroupWidget = new mw.echo.ui.DatedSubGroupListWidget(
			this.controller,
			models[ model ],
			{
				showTitle: true,
				showMarkAllRead: true,
				$overlay: this.$overlay,
				animated: this.animateSorting
			}
		);
		this.attachModel( model, models[ model ] );

		subgroupWidget.resetItemsFromModel();
		groupWidgets.push( subgroupWidget );
	}

	this.getList().getItems().forEach( ( widget ) => {
		// Destroy all available widgets
		widget.destroy();
	} );

	// Reset the list and re-add the items
	this.getList().clearItems();
	this.getList().addItems( groupWidgets );
};

/**
 * Attach a model to the widget
 *
 * @param {string} modelId Symbolic name for the model
 * @param {mw.echo.dm.SortedList} model Notifications list model
 */
mw.echo.ui.DatedNotificationsWidget.prototype.attachModel = function ( modelId, model ) {
	this.models[ modelId ] = model;
};

/**
 * Detach a model from the widget
 *
 * @param {string} modelId Notifications list model
 */
mw.echo.ui.DatedNotificationsWidget.prototype.detachModel = function ( modelId ) {
	this.models[ modelId ].disconnect( this );
	delete this.models[ modelId ];
};

/**
 * Get the list widget contained in this item
 *
 * @return {mw.echo.ui.SortedListWidget} List widget
 */
mw.echo.ui.DatedNotificationsWidget.prototype.getList = function () {
	return this.listWidget;
};

/**
 * Get the number of all notifications in all sections of the widget
 *
 * @return {number} The number of all notifications
 */
mw.echo.ui.DatedNotificationsWidget.prototype.getAllNotificationCount = function () {
	const groups = this.getList().getItems();

	let count = 0;
	for ( let i = 0; i < groups.length; i++ ) {
		count += groups[ i ].getListWidget().getItemCount();
	}

	return count;
};
