/*!
 * VisualEditor UserInterface MobileContext class.
 *
 * @copyright See AUTHORS.txt
 */

/**
 * UserInterface context that displays inspector full screen.
 *
 * @class
 * @extends ve.ui.LinearContext
 *
 * @constructor
 * @param {ve.ui.Surface} surface
 * @param {Object} [config] Configuration options
 */
ve.ui.MobileContext = function VeUiMobileContext() {
	// Parent constructor
	ve.ui.MobileContext.super.apply( this, arguments );

	this.openingTimeout = null;

	this.closeButton = new OO.ui.ButtonWidget( {
		classes: [ 've-ui-mobileContext-close' ],
		framed: false,
		label: ve.msg( 'visualeditor-contextitemwidget-label-close' ),
		invisibleLabel: true,
		icon: 'close'
	} );

	// Events
	this.closeButton.connect( this, { click: 'onCloseButtonClick' } );
	this.inspectors.connect( this, {
		setup: [ 'toggle', true ],
		teardown: [ 'toggle', false ]
	} );

	// Initialization
	this.$element.addClass( 've-ui-mobileContext' );
	this.$group.addClass( 've-ui-mobileContext-menu' );
	this.surface.getGlobalOverlay().$element.append( this.inspectors.$element );
};

/* Inheritance */

OO.inheritClass( ve.ui.MobileContext, ve.ui.LinearContext );

/* Static Properties */

ve.ui.MobileContext.static.isMobile = true;

/* Methods */

/**
 * Handle click events from the close button
 */
ve.ui.MobileContext.prototype.onCloseButtonClick = function () {
	this.hide();
	ve.track( 'activity.mobileContext', { action: 'context-close' } );
};

/**
 * @inheritdoc
 */
ve.ui.MobileContext.prototype.setupMenuItems = function () {
	// Parent method
	ve.ui.MobileContext.super.prototype.setupMenuItems.apply( this, arguments );

	// Ensure close button is at start after $group has been modified.
	this.$group.prepend( this.closeButton.$element );
};

/**
 * @inheritdoc
 */
ve.ui.MobileContext.prototype.createInspectorWindowManager = function () {
	return new ve.ui.MobileWindowManager( this.surface, {
		factory: ve.ui.windowFactory,
		overlay: this.surface.getGlobalOverlay()
	} );
};

/**
 * Stripped down version of onInspectorOpening as we don't need to hide/show
 * the context because the inspector is full screen.
 *
 * @inheritdoc
 */
ve.ui.MobileContext.prototype.onInspectorOpening = function ( win, opening ) {
	const observer = this.surface.getView().surfaceObserver;

	this.inspector = win;

	// Shut down the SurfaceObserver as soon as possible, so it doesn't get confused
	// by the selection moving around in IE. Will be reenabled when inspector closes.
	// FIXME this should be done in a nicer way, managed by the Surface classes
	observer.pollOnce();
	observer.stopTimerLoop();

	opening
		.then( ( opened ) => {
			opened.then( ( closed ) => {
				closed.always( () => {
					this.inspector = null;
					// Reenable observer
					observer.startTimerLoop();
					this.afterContextChange();
				} );
			} );
		} );
};

/**
 * @inheritdoc
 */
ve.ui.MobileContext.prototype.toggleMenu = function ( show ) {
	show = show === undefined ? !this.choosing : !!show;

	if ( show !== this.choosing ) {
		if ( show ) {
			if ( this.hideMenuTimeout ) {
				clearTimeout( this.hideMenuTimeout );
				// Ensure menu is torn down before setting up again.
				ve.ui.MobileContext.super.prototype.toggleMenu.call( this, false );
			}
			// Parent method
			ve.ui.MobileContext.super.prototype.toggleMenu.call( this, true );
		} else {
			this.hideMenuTimeout = setTimeout( () => {
				// Parent method
				ve.ui.MobileContext.super.prototype.toggleMenu.call( this, false );
			}, 100 );
		}
	}

	return this;
};

/**
 * @inheritdoc
 */
ve.ui.MobileContext.prototype.toggle = function ( show ) {
	show = show === undefined ? !this.visible : !!show;
	if ( show && !this.visible ) {
		const deferred = ve.createDeferred();
		// Set opening flag immediately
		this.openingTimeout = setTimeout( () => {
			// Parent method
			ve.ui.MobileContext.super.prototype.toggle.call( this, true );
			this.emit( 'resize' );
			deferred.resolve();
			this.openingTimeout = null;
		}, 250 );
		return deferred;
	} else {
		if ( this.openingTimeout ) {
			clearTimeout( this.openingTimeout );
			this.openingTimeout = null;
		}
		setTimeout( () => {
			this.emit( 'resize' );
		}, 100 );
		// Parent method
		return ve.ui.MobileContext.super.prototype.toggle.call( this, show );
	}
};

/**
 * @inheritdoc
 */
ve.ui.MobileContext.prototype.isVisible = function () {
	return this.visible || !!this.openingTimeout;
};

/**
 * @inheritdoc
 */
ve.ui.MobileContext.prototype.isInspectable = function () {
	// Parent method
	return ve.ui.MobileContext.super.prototype.isInspectable.call( this ) &&
		// Suppress context when virtual keyboard is visible
		!this.getSurface().getTarget().isVirtualKeyboardOpen();
};

/**
 * @inheritdoc
 */
ve.ui.MobileContext.prototype.getSurfacePadding = function () {
	return { bottom: this.$element[ 0 ].clientHeight };
};
