/*

Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.

For licensing, see LICENSE.html or http://ckeditor.com/license

*/



CKEDITOR.dialog.add( 'colordialog', function( editor )

	{

		// Define some shorthands.

		var $el = CKEDITOR.dom.element,

			$doc = CKEDITOR.document,

			lang = editor.lang.colordialog;



		// Reference the dialog.

		var dialog;



		var spacer =

		{

			type : 'html',

			html : '&nbsp;'

		};



		var selected;



		function clearSelected()

		{

			$doc.getById( selHiColorId ).removeStyle( 'background-color' );

			dialog.getContentElement( 'picker', 'selectedColor' ).setValue( '' );

			selected && selected.removeAttribute( 'aria-selected' );

			selected = null;

		}



		function updateSelected( evt )

		{

			var target = evt.data.getTarget(),

				color;



			if ( target.getName() == 'td' &&

				 ( color = target.getChild( 0 ).getHtml() ) )

			{

				selected = target;

				selected.setAttribute( 'aria-selected', true );

				dialog.getContentElement( 'picker', 'selectedColor' ).setValue( color );

			}

		}



		// Basing black-white decision off of luma scheme using the Rec. 709 version

		function whiteOrBlack( color )

		{

			color = color.replace( /^#/, '' );

			for ( var i = 0, rgb = []; i <= 2; i++ )

				rgb[i] = parseInt( color.substr( i * 2, 2 ), 16 );

			var luma = (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]);

			return '#' + ( luma >= 165 ? '000' : 'fff' );

		}



		// Distinguish focused and hover states.

		var focused, hovered;



		// Apply highlight style.

		function updateHighlight( event )

		{

			// Convert to event.

			!event.name && ( event = new CKEDITOR.event( event ) );



			var isFocus = !(/mouse/).test( event.name ),

				target = event.data.getTarget(),

				color;



			if ( target.getName() == 'td' && ( color = target.getChild( 0 ).getHtml() ) )

			{

				removeHighlight( event );



				isFocus ? focused = target : hovered = target;



				// Apply outline style to show focus.

				if ( isFocus )

				{

					target.setStyle( 'border-color', whiteOrBlack( color ) );

					target.setStyle( 'border-style', 'dotted' );

				}



				$doc.getById( hicolorId ).setStyle( 'background-color', color );

				$doc.getById( hicolorTextId ).setHtml( color );

			}

		}



		function clearHighlight()

		{

			var color = focused.getChild( 0 ).getHtml();

			focused.setStyle( 'border-color', color );

			focused.setStyle( 'border-style', 'solid' );

			$doc.getById( hicolorId ).removeStyle( 'background-color' );

			$doc.getById( hicolorTextId ).setHtml( '&nbsp;' );

			focused = null;

		}



		// Remove previously focused style.

		function removeHighlight( event )

		{

			var isFocus = !(/mouse/).test( event.name ),

				target = isFocus && focused;



			if ( target )

			{

				var color = target.getChild( 0 ).getHtml();

				target.setStyle( 'border-color', color );

				target.setStyle( 'border-style', 'solid' );

			}



			if ( ! ( focused || hovered ) )

			{

				$doc.getById( hicolorId ).removeStyle( 'background-color' );

				$doc.getById( hicolorTextId ).setHtml( '&nbsp;' );

			}

		}



		function onKeyStrokes( evt )

		{

			var domEvt = evt.data;



			var element = domEvt.getTarget();

			var relative, nodeToMove;

			var keystroke = domEvt.getKeystroke(),

				rtl = editor.lang.dir == 'rtl';



			switch ( keystroke )

			{

				// UP-ARROW

				case 38 :

					// relative is TR

					if ( ( relative = element.getParent().getPrevious() ) )

					{

						nodeToMove = relative.getChild( [ element.getIndex() ] );

						nodeToMove.focus();

					}

					domEvt.preventDefault();

					break;

				// DOWN-ARROW

				case 40 :

					// relative is TR

					if ( ( relative = element.getParent().getNext() ) )

					{

						nodeToMove = relative.getChild( [ element.getIndex() ] );

						if ( nodeToMove && nodeToMove.type == 1 )

						{

							nodeToMove.focus();

						}

					}

					domEvt.preventDefault();

					break;



				// SPACE

				// ENTER

				case 32 :

				case 13 :

					updateSelected( evt );

					domEvt.preventDefault();

					break;



				// RIGHT-ARROW

				case rtl ? 37 : 39 :

					// relative is TD

					if ( ( nodeToMove = element.getNext() ) )

					{

						if ( nodeToMove.type == 1 )

						{

							nodeToMove.focus();

							domEvt.preventDefault( true );

						}

					}

					// relative is TR

					else if ( ( relative = element.getParent().getNext() ) )

					{

						nodeToMove = relative.getChild( [ 0 ] );

						if ( nodeToMove && nodeToMove.type == 1 )

						{

							nodeToMove.focus();

							domEvt.preventDefault( true );

						}

					}

					break;



				// LEFT-ARROW

				case rtl ? 39 : 37 :

					// relative is TD

					if ( ( nodeToMove = element.getPrevious() ) )

					{

						nodeToMove.focus();

						domEvt.preventDefault( true );

					}

					// relative is TR

					else if ( ( relative = element.getParent().getPrevious() ) )

					{

						nodeToMove = relative.getLast();

						nodeToMove.focus();

						domEvt.preventDefault( true );

					}

					break;

				default :

					// Do not stop not handled events.

					return;

			}

		}



		function createColorTable()

		{

			table = CKEDITOR.dom.element.createFromHtml

			(

				'<table tabIndex="-1" aria-label="' + lang.options + '"' +

				' role="grid" style="border-collapse:separate;" cellspacing="0">' +

				'<caption class="cke_voice_label">' + lang.options + '</caption>' +

				'<tbody role="presentation"></tbody></table>'

			);



			table.on( 'mouseover', updateHighlight );

			table.on( 'mouseout', removeHighlight );



			// Create the base colors array.

			var aColors = [ '00', '33', '66', '99', 'cc', 'ff' ];



			// This function combines two ranges of three values from the color array into a row.

			function appendColorRow( rangeA, rangeB )

			{

				for ( var i = rangeA ; i < rangeA + 3 ; i++ )

				{

					var row = new $el( table.$.insertRow( -1 ) );

					row.setAttribute( 'role', 'row' );



					for ( var j = rangeB ; j < rangeB + 3 ; j++ )

					{

						for ( var n = 0 ; n < 6 ; n++ )

						{

							appendColorCell( row.$, '#' + aColors[j] + aColors[n] + aColors[i] );

						}

					}

				}

			}



			// This function create a single color cell in the color table.

			function appendColorCell( targetRow, color )

			{

				var cell = new $el( targetRow.insertCell( -1 ) );

				cell.setAttribute( 'class', 'ColorCell' );

				cell.setAttribute( 'tabIndex', -1 );

				cell.setAttribute( 'role', 'gridcell' );



				cell.on( 'keydown', onKeyStrokes );

				cell.on( 'click', updateSelected );

				cell.on( 'focus', updateHighlight );

				cell.on( 'blur', removeHighlight );



				cell.setStyle( 'background-color', color );

				cell.setStyle( 'border', '1px solid ' + color );



				cell.setStyle( 'width', '14px' );

				cell.setStyle( 'height', '14px' );



				var colorLabel = numbering( 'color_table_cell' );

				cell.setAttribute( 'aria-labelledby',colorLabel );

				cell.append( CKEDITOR.dom.element.createFromHtml( '<span id="' + colorLabel + '" class="cke_voice_label">' + color + '</span>', CKEDITOR.document ) );

			}



			appendColorRow( 0, 0 );

			appendColorRow( 3, 0 );

			appendColorRow( 0, 3 );

			appendColorRow( 3, 3 );



			// Create the last row.

			var oRow = new $el( table.$.insertRow( -1 ) ) ;

			oRow.setAttribute( 'role', 'row' );



			// Create the gray scale colors cells.

			for ( var n = 0 ; n < 6 ; n++ )

			{

				appendColorCell( oRow.$, '#' + aColors[n] + aColors[n] + aColors[n] ) ;

			}



			// Fill the row with black cells.

			for ( var i = 0 ; i < 12 ; i++ )

			{

				appendColorCell( oRow.$, '#000000' ) ;

			}

		}



		var numbering = function( id )

			{

				return CKEDITOR.tools.getNextId() + '_' + id;

			},

			hicolorId = numbering( 'hicolor' ),

			hicolorTextId = numbering( 'hicolortext' ),

			selHiColorId = numbering( 'selhicolor' ),

			table;



		createColorTable();



		return {

			title : lang.title,

			minWidth : 360,

			minHeight : 220,

			onLoad : function()

			{

				// Update reference.

				dialog = this;

			},

			onHide : function()

			{

				clearSelected();

				clearHighlight();

			},

			contents : [

				{

					id : 'picker',

					label : lang.title,

					accessKey : 'I',

					elements :

					[

						{

							type : 'hbox',

							padding : 0,

							widths : [ '70%', '10%', '30%' ],

							children :

							[

								{

									type : 'html',

									html :	'<div></div>',

									onLoad : function()

									{

										CKEDITOR.document.getById( this.domId ).append( table );

									},

									focus : function()

									{

										// Restore the previously focused cell,

										// otherwise put the initial focus on the first table cell.

										( focused || this.getElement().getElementsByTag( 'td' ).getItem( 0 ) ).focus();

									}

								},

								spacer,

								{

									type : 'vbox',

									padding : 0,

									widths : [ '70%', '5%', '25%' ],

									children :

									[

										{

											type : 'html',

											html : '<span>' + lang.highlight +'</span>\

												<div id="' + hicolorId + '" style="border: 1px solid; height: 74px; width: 74px;"></div>\

												<div id="' + hicolorTextId + '">&nbsp;</div><span>' + lang.selected + '</span>\

												<div id="' + selHiColorId + '" style="border: 1px solid; height: 20px; width: 74px;"></div>'

										},

										{

											type : 'text',

											label : lang.selected,

											labelStyle: 'display:none',

											id : 'selectedColor',

											style : 'width: 74px',

											onChange : function()

											{

												// Try to update color preview with new value. If fails, then set it no none.

												try

												{

													$doc.getById( selHiColorId ).setStyle( 'background-color', this.getValue() );

												}

												catch ( e )

												{

													clearSelected();

												}

											}

										},

										spacer,

										{

											type : 'button',

											id : 'clear',

											style : 'margin-top: 5px',

											label : lang.clear,

											onClick : clearSelected

										}

									]

								}

							]

						}

					]

				}

			]

		};

	}

	);

