/* bender-tags: editor */
/* bender-ckeditor-plugins: dialog */

( function() {
	'use strict';

	CKEDITOR.on( 'instanceLoaded', function() {
		CKEDITOR.dialog.add( 'testDialog1', function() {
			return {
				title: 'Test Dialog 1',
				contents: [
					{
						id: 'info',
						label: 'Test',
						elements: [
							{
								type: 'text',
								id: 'foo',
								label: 'bar'
							}
						]
					}
				]
			};
		} );
		CKEDITOR.dialog.add( 'testDialog2', '%TEST_DIR%_assets/testdialog.js' );
	} );

	bender.editor = {};

	bender.test( {
		'test open dialog from local': function() {
			var ed = this.editor, tc = this;
			ed.openDialog( 'testDialog1', function( dialog ) {
				tc.resume( function() {
					assert.isNotNull( dialog );

					wait( function() {
						dialog.getButton( 'cancel' ).click();
					}, 100 );
				} );
			} );
			tc.wait();
		},

		'test open dialog from url': function() {
			var ed = this.editor, tc = this;
			ed.openDialog( 'testDialog2', function( dialog ) {
				tc.resume( function() {
					assert.isNotNull( dialog );

					wait( function() {
						dialog.getButton( 'cancel' ).click();
					}, 100 );
				} );
			} );
			tc.wait();
		},

		// Code of this test is poor (checking isVisible and operations on DOM), but that's caused
		// by very closed and poor dialog API.
		'test dialog\'s field are disabled when not allowed': function() {
			var ed = this.editor;

			CKEDITOR.dialog.add( 'testDialog3', function() {
				return {
					title: 'Test Dialog 3',
					contents: [
						{
							id: 'tab1',
							label: 'Test 1',
							elements: [
								{
									type: 'text',
									id: 'foo',
									label: 'foo',
									requiredContent: 'p'
								},
								{
									type: 'text',
									id: 'bar',
									label: 'bar',
									requiredContent: 'x'
								}
							]
						},
						{
							id: 'tab2',
							label: 'Test 2',
							elements: [
								// vbox shouldn't be count as visible uielement,
								// so entire tab2 should be hidden.
								{
									type: 'vbox',
									children: [
										{
											type: 'text',
											id: 'bom',
											label: 'bom',
											requiredContent: 'y'
										}
									]
								}
							]
						},
						{
							id: 'tab3',
							label: 'Test 3',
							elements: [
								{
									type: 'text',
									id: 'bim',
									label: 'bim'
								}
							]
						}
					]
				};
			} );

			ed.openDialog( 'testDialog3', function( dialog ) {
				setTimeout( function() {
					resume( function() {
						// Tab 2 has no visible elements, so it should be hidden.
						assert.areSame( 2, dialog.getPageCount() );
						assert.isTrue( dialog.parts.tabs.getChild( 0 ).isVisible() );
						assert.isFalse( dialog.parts.tabs.getChild( 1 ).isVisible() );
						assert.isTrue( dialog.parts.tabs.getChild( 2 ).isVisible() );

						assert.isTrue( dialog.getContentElement( 'tab1', 'foo' ).getInputElement().isVisible() );
						assert.isFalse( dialog.getContentElement( 'tab1', 'bar' ).getInputElement().isVisible() );
						assert.isFalse( dialog.getContentElement( 'tab2', 'bom' ).getInputElement().isVisible() );

						// Element tab2:bom should be still invisible after switching to second tab.
						dialog.selectPage( 'tab2' );
						assert.isFalse( dialog.getContentElement( 'tab2', 'bom' ).getInputElement().isVisible() );

						dialog.selectPage( 'tab3' );
						assert.isTrue( dialog.getContentElement( 'tab3', 'bim' ).getInputElement().isVisible() );

						wait( function() {
							dialog.getButton( 'cancel' ).click();
						}, 100 );
					} );
				}, 200 );
			} );
			wait();
		},

		// Code of this test is poor (checking isVisible and operations on DOM), but that's caused
		// by very closed and poor dialog API.
		// https://dev.ckeditor.com/ticket/12546
		'test dialog\'s HTML field always count as allowed field unless requiredContent is specified': function() {
			var ed = this.editor;

			CKEDITOR.dialog.add( 'testDialog4', function() {
				return {
					title: 'Test Dialog 4',
					contents: [
						{
							id: 'tab1',
							label: 'Test 1',
							elements: [
								{
									type: 'html',
									id: 'field1',
									html: 'foo'
								}
							]
						},
						{
							id: 'tab2a',
							label: 'Test 2a',
							elements: [
								{
									type: 'html',
									id: 'field2a',
									html: 'foo',
									requiredContent: 'x'
								}
							]
						},
						{
							id: 'tab2b',
							label: 'Test 2b',
							elements: [
								{
									type: 'html',
									id: 'field2b',
									html: 'foo',
									requiredContent: 'p'
								}
							]
						},
						{
							id: 'tab3',
							label: 'Test 3',
							requiredContent: 'y',
							elements: [
								{
									type: 'html',
									id: 'field3',
									html: 'foo'
								}
							]
						}
					]
				};
			} );

			ed.openDialog( 'testDialog4', function( dialog ) {
				setTimeout( function() {
					resume( function() {
						assert.areSame( 2, dialog.getPageCount() );
						assert.isTrue( dialog.parts.tabs.getChild( 0 ).isVisible(), 'tab1' );
						// Tab 2a is hidden.
						assert.isFalse( dialog.parts.tabs.getChild( 1 ).isVisible(), 'tab2a' );
						assert.isTrue( dialog.parts.tabs.getChild( 2 ).isVisible(), 'tab2b' );
						// Tab 3 wasn't created at all.
						assert.isNull( dialog.parts.tabs.getChild( 3 ), 'tab3' );

						assert.isTrue( dialog.getContentElement( 'tab1', 'field1' ).getInputElement().isVisible(), 'field1' );

						dialog.selectPage( 'tab2b' );
						assert.isTrue( dialog.getContentElement( 'tab2b', 'field2b' ).getInputElement().isVisible(), 'field2b' );

						wait( function() {
							dialog.getButton( 'cancel' ).click();
						}, 100 );
					} );
				}, 200 );
			} );
			wait();
		},

		'test dialog is triggered on doubleclick': function() {
			var editor = this.editor,
			openedDialog = null,
			revert = bender.tools.replaceMethod( editor, 'openDialog', function( name ) {
				openedDialog = name;
			} );

			editor.fire( 'doubleclick', { element: editor.editable() } );

			assert.isNull( openedDialog, 'dialog was not opened' );

			editor.once( 'doubleclick', function( evt ) {
				evt.data.dialog = 'testdoubleclick';
			} );

			editor.fire( 'doubleclick', { element: editor.editable() } );

			assert.areSame( 'testdoubleclick', openedDialog, 'dialog was opened on doubleclick' );

			revert();
		},

		'test dialog setState': function() {
			var stateEventFired = 0,
			editor = this.editor;

			CKEDITOR.dialog.add( 'testDialog5', function() {
				return {
					title: 'Test Dialog 5',
					contents: [
						{
							id: 'tab1',
							label: 'Test 1',
							elements: [
								{
									type: 'text',
									id: 'foo',
									label: 'foo',
									requiredContent: 'p'
								}
							]
						}
					]
				};
			} );

			editor.addCommand( 'testDialog5', new CKEDITOR.dialogCommand( 'testDialog5' ) );

			editor.once( 'dialogShow', function( evt ) {
				var dialog = evt.data;

				resume( function() {
					try {
						assert.isTrue( dialog.getButton( 'ok' ).isEnabled(), 'OK button is enabled.' );
						assert.isUndefined( dialog.parts.spinner, 'By default dialog has no spinner' );
						assert.areSame( CKEDITOR.DIALOG_STATE_IDLE, dialog.state, 'Default dialog state' );

						var stateListener = dialog.on( 'state', function( evt ) {
							try {
								assert.areSame( CKEDITOR.DIALOG_STATE_BUSY, dialog.state, 'New dialog state' );
								assert.isFalse( dialog.getButton( 'ok' ).isEnabled(), 'OK button is disabled' );
								assert.isObject( dialog.parts.spinner, 'Dialog has a spinner element' );

								++stateEventFired;
							} catch ( e ) {
								evt.removeListener();
								throw e;
							}
						} );

						// Change dialog's state and assert related properties.
						dialog.setState( CKEDITOR.DIALOG_STATE_BUSY );

						// Remove the listener because the dialog will be reopened and those assertions would be invalid.
						stateListener.removeListener();

						assert.areSame( 1, stateEventFired, 'State event has been fired' );

						dialog.hide();

						// Call the dialog again to tell what happens to the state and the UI once reopened.
						editor.execCommand( 'testDialog5' );

						editor.once( 'dialogShow', function( evt ) {
							var dialog = evt.data;

							resume( function() {
								try {
									assert.areSame( CKEDITOR.DIALOG_STATE_IDLE, dialog.state, 'Default dialog state after re–open' );
									assert.isTrue( dialog.getButton( 'ok' ).isEnabled(), 'OK button is enabled after re–open' );
									assert.isObject( dialog.parts.spinner, 'Dialog has been given a spinner before' );
								} catch ( e ) {
									throw e;
								} finally {
									dialog.hide();
								}
							} );
						} );

						wait();
					} catch ( e ) {
						throw e;
					} finally {
						dialog.hide();
					}
				} );
			} );

			editor.execCommand( 'testDialog5' );

			wait();
		},

		// #830
		'test dialog opens tab defined in tabId as default': function() {
			var editor = this.editor;

			CKEDITOR.dialog.add( 'testDialog6', function() {
				return {
					title: 'Test dialog 6',
					contents: [
						{
							id: 'tab1',
							label: 'Tab one',
							elements: [
								{
									type: 'html',
									id: 'field11',
									html: 'foo'
								}
							]
						},
						{
							id: 'tab2',
							label: 'Tab two',
							elements: [
								{
									type: 'html',
									id: 'field21',
									html: 'bar'
								}
							]
						}
					]
				};
			} );

			editor.addCommand( 'testDialog6', new CKEDITOR.dialogCommand( 'testDialog6', {
				tabId: 'tab2'
			} ) );


			editor.once( 'dialogShow', function( evt ) {
				resume( function() {
					try {
						var dialog = evt.data;
						assert.areSame( 'tab2', dialog._.currentTabId );
					} catch ( e ) {
						throw e;
					}
					finally {
						dialog.hide();
					}
				} );
			} );

			editor.execCommand( 'testDialog6' );
			wait();
		}
	} );

} )();
