const
	mfExtend = require( '../mobile.startup/mfExtend' ),
	PageList = require( '../mobile.startup/PageList' ),
	WatchstarPageList = require( '../mobile.startup/watchstar/WatchstarPageList' ),
	ScrollEndEventEmitter = require( './ScrollEndEventEmitter' ),
	util = require( '../mobile.startup/util' ),
	WatchListGateway = require( './WatchListGateway' );

/**
 * An extension of the WatchstarPageList which preloads pages as all being
 * watched.
 *
 * @extends WatchstarPageList
 * @class WatchList
 * @uses ScrollEndEventEmitter
 *
 * @fires watched
 * @fires watch
 * @param {Object} params Configuration options
 * @param {OO.EventEmitter} params.eventBus Object used to listen for scroll:throttled events
 * @private
 */
function WatchList( params ) {
	let lastTitle;
	const options = util.extend(
		{},
		{
			isBorderBox: false
		},
		params
	);

	// Set up infinite scroll helper and listen to events
	this.scrollEndEventEmitter = new ScrollEndEventEmitter( options.eventBus );
	this.scrollEndEventEmitter.on( ScrollEndEventEmitter.EVENT_SCROLL_END,
		this._loadPages.bind( this ) );

	if ( options.el ) {
		lastTitle = this.getLastTitle( options.el );
	}
	this.gateway = new WatchListGateway( options.api, lastTitle );

	WatchstarPageList.call( this, options );
}

mfExtend( WatchList, WatchstarPageList, {
	/**
	 * @inheritdoc
	 * @memberof WatchList
	 * @instance
	 */
	preRender: function () {
		// The DOM will be modified. Prevent any false scroll end events from
		// being emitted.
		this.scrollEndEventEmitter.disable();
		this.scrollEndEventEmitter.setElement( this.$el );
	},
	/**
	 * Also sets a watch uploads funnel.
	 *
	 * @inheritdoc
	 * @memberof WatchList
	 * @instance
	 */
	postRender: function () {
		// Skip a level from WatchstarPageList directly to PageList.
		PageList.prototype.postRender.apply( this );

		const $items = this.queryUnitializedItems();

		// WatchList requests list of watched pages. The list contains only
		// watched pages so it's safe to transform the title map to a status map
		// with each entry marked watched (true).
		const statuses = Object.keys( this.parsePagesFromItems( $items ) )
			.reduce( function ( arr, title ) {
				arr[ title ] = true;
				return arr;
			}, {} );
		this.renderItems( $items, statuses );

		// The list has been extended. Re-enable scroll end events.
		this.scrollEndEventEmitter.enable();
	},

	/**
	 * Loads pages from the api and triggers render.
	 * Infinite scroll is re-enabled in postRender.
	 *
	 * @memberof WatchList
	 * @instance
	 */
	_loadPages: function () {
		this.gateway.loadWatchlist().then( function ( pages ) {
			pages.forEach( function ( page ) {
				this.appendPage( page );
			}.bind( this ) );
			this.render();
		}.bind( this ) );
	},

	/**
	 * Appends a list item
	 *
	 * @memberof WatchList
	 * @instance
	 * @param {Page} page
	 */
	appendPage: function ( page ) {
		// wikidata descriptions should not show in this view.
		const templateOptions = util.extend( {}, page, {
			wikidataDescription: undefined
		} );
		this.$el.append( this.templatePartials.item.render( templateOptions ) );
	},

	/**
	 * Get the last title from the rendered HTML.
	 * Used for initializing the API
	 *
	 * @memberof WatchList
	 * @instance
	 * @param {jQuery.Object} $el Dom element of the list
	 * @return {string}
	 */
	getLastTitle: function ( $el ) {
		return $el.find( 'li' ).last().attr( 'title' );
	}
} );

module.exports = WatchList;
