/**
 * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */

/**
 * @fileOverview The "show border" plugin. The command display visible outline
 * border line around all table elements if table doesn't have a none-zero 'border' attribute specified.
 */

( function() {
	var commandDefinition = {
		preserveState: true,
		editorFocus: false,
		readOnly: 1,

		exec: function( editor ) {
			this.toggleState();
			this.refresh( editor );
		},

		refresh: function( editor ) {
			if ( editor.document ) {
				var funcName = ( this.state == CKEDITOR.TRISTATE_ON ) ? 'attachClass' : 'removeClass';
				editor.editable()[ funcName ]( 'cke_show_borders' );
			}
		}
	};

	var showBorderClassName = 'cke_show_border';

	CKEDITOR.plugins.add( 'showborders', {
		modes: { 'wysiwyg': 1 },

		onLoad: function() {
			var cssStyleText,
				cssTemplate =
			// TODO: For IE6, we don't have child selector support,
			// where nested table cells could be incorrect.
			( CKEDITOR.env.ie6Compat ? [
				'.%1 table.%2,',
				'.%1 table.%2 td, .%1 table.%2 th',
				'{',
				'border : #d3d3d3 1px dotted',
				'}'
			] : [
				'.%1 table.%2,',
				'.%1 table.%2 > tr > td, .%1 table.%2 > tr > th,',
				'.%1 table.%2 > tbody > tr > td, .%1 table.%2 > tbody > tr > th,',
				'.%1 table.%2 > thead > tr > td, .%1 table.%2 > thead > tr > th,',
				'.%1 table.%2 > tfoot > tr > td, .%1 table.%2 > tfoot > tr > th',
				'{',
				'border : #d3d3d3 1px dotted',
				'}'
			] ).join( '' );

			cssStyleText = cssTemplate.replace( /%2/g, showBorderClassName ).replace( /%1/g, 'cke_show_borders ' );

			CKEDITOR.addCss( cssStyleText );
		},

		init: function( editor ) {

			var command = editor.addCommand( 'showborders', commandDefinition );
			command.canUndo = false;

			if ( editor.config.startupShowBorders !== false )
				command.setState( CKEDITOR.TRISTATE_ON );

			// Refresh the command on setData.
			editor.on( 'mode', function() {
				if ( command.state != CKEDITOR.TRISTATE_DISABLED )
					command.refresh( editor );
			}, null, null, 100 );

			// Refresh the command on wysiwyg frame reloads.
			editor.on( 'contentDom', function() {
				if ( command.state != CKEDITOR.TRISTATE_DISABLED )
					command.refresh( editor );
			} );

			editor.on( 'removeFormatCleanup', function( evt ) {
				var element = evt.data;
				if ( editor.getCommand( 'showborders' ).state == CKEDITOR.TRISTATE_ON && element.is( 'table' ) && ( !element.hasAttribute( 'border' ) || parseInt( element.getAttribute( 'border' ), 10 ) <= 0 ) )
					element.addClass( showBorderClassName );
			} );
		},

		afterInit: function( editor ) {
			var dataProcessor = editor.dataProcessor,
				dataFilter = dataProcessor && dataProcessor.dataFilter,
				htmlFilter = dataProcessor && dataProcessor.htmlFilter;

			if ( dataFilter ) {
				dataFilter.addRules( {
					elements: {
						'table': function( element ) {
							var attributes = element.attributes,
								cssClass = attributes[ 'class' ],
								border = parseInt( attributes.border, 10 );

							if ( ( !border || border <= 0 ) && ( !cssClass || cssClass.indexOf( showBorderClassName ) == -1 ) )
								attributes[ 'class' ] = ( cssClass || '' ) + ' ' + showBorderClassName;
						}
					}
				} );
			}

			if ( htmlFilter ) {
				htmlFilter.addRules( {
					elements: {
						'table': function( table ) {
							var attributes = table.attributes,
								cssClass = attributes[ 'class' ];

							cssClass && ( attributes[ 'class' ] = cssClass.replace( showBorderClassName, '' ).replace( /\s{2}/, ' ' ).replace( /^\s+|\s+$/, '' ) );
						}
					}
				} );
			}
		}
	} );

	// Table dialog must be aware of it.
	CKEDITOR.on( 'dialogDefinition', function( ev ) {
		var dialogName = ev.data.name;

		if ( dialogName == 'table' || dialogName == 'tableProperties' ) {
			var dialogDefinition = ev.data.definition,
				infoTab = dialogDefinition.getContents( 'info' ),
				borderField = infoTab.get( 'txtBorder' ),
				originalCommit = borderField.commit;

			borderField.commit = CKEDITOR.tools.override( originalCommit, function( org ) {
				return function( data, selectedTable ) {
					org.apply( this, arguments );
					var value = parseInt( this.getValue(), 10 );
					selectedTable[ ( !value || value <= 0 ) ? 'addClass' : 'removeClass' ]( showBorderClassName );
				};
			} );

			var advTab = dialogDefinition.getContents( 'advanced' ),
				classField = advTab && advTab.get( 'advCSSClasses' );

			if ( classField ) {
				classField.setup = CKEDITOR.tools.override( classField.setup, function( originalSetup ) {
					return function() {
						originalSetup.apply( this, arguments );
						this.setValue( this.getValue().replace( /cke_show_border/, '' ) );
					};
				} );

				classField.commit = CKEDITOR.tools.override( classField.commit, function( originalCommit ) {
					return function( data, element ) {
						originalCommit.apply( this, arguments );

						if ( !parseInt( element.getAttribute( 'border' ), 10 ) )
							element.addClass( 'cke_show_border' );
					};
				} );
			}
		}
	} );

} )();

/**
 * Whether to automatically enable the "show borders" command when the editor loads.
 *
 *		config.startupShowBorders = false;
 *
 * @cfg {Boolean} [startupShowBorders=true]
 * @member CKEDITOR.config
 */
