/*
Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
/**
 * @fileOverview Defines the {@link CKEDITOR.dom.document} class, which
 *		represents a DOM document.
 */
/**
 * Represents a DOM document.
 * @constructor
 * @augments CKEDITOR.dom.domObject
 * @param {Object} domDocument A native DOM document.
 * @example
 * var document = new CKEDITOR.dom.document( document );
 */
CKEDITOR.dom.document = function( domDocument )
{
	CKEDITOR.dom.domObject.call( this, domDocument );
};
// PACKAGER_RENAME( CKEDITOR.dom.document )
CKEDITOR.dom.document.prototype = new CKEDITOR.dom.domObject();
CKEDITOR.tools.extend( CKEDITOR.dom.document.prototype,
	/** @lends CKEDITOR.dom.document.prototype */
	{
		/**
		 * Appends a CSS file to the document.
		 * @param {String} cssFileUrl The CSS file URL.
		 * @example
		 * CKEDITOR.document.appendStyleSheet( '/mystyles.css' );
		 */
		appendStyleSheet : function( cssFileUrl )
		{
			if ( this.$.createStyleSheet )
				this.$.createStyleSheet( cssFileUrl );
			else
			{
				var link = new CKEDITOR.dom.element( 'link' );
				link.setAttributes(
					{
						rel		:'stylesheet',
						type	: 'text/css',
						href	: cssFileUrl
					});
				this.getHead().append( link );
			}
		},
		appendStyleText : function( cssStyleText )
		{
			if ( this.$.createStyleSheet )
			{
				var styleSheet = this.$.createStyleSheet( "" );
				styleSheet.cssText = cssStyleText ;
			}
			else
			{
				var style = new CKEDITOR.dom.element( 'style', this );
				style.append( new CKEDITOR.dom.text( cssStyleText, this ) );
				this.getHead().append( style );
			}
		},
		createElement : function( name, attribsAndStyles )
		{
			var element = new CKEDITOR.dom.element( name, this );
			if ( attribsAndStyles )
			{
				if ( attribsAndStyles.attributes )
					element.setAttributes( attribsAndStyles.attributes );
				if ( attribsAndStyles.styles )
					element.setStyles( attribsAndStyles.styles );
			}
			return element;
		},
		createText : function( text )
		{
			return new CKEDITOR.dom.text( text, this );
		},
		focus : function()
		{
			this.getWindow().focus();
		},
		/**
		 * Gets and element based on its id.
		 * @param {String} elementId The element id.
		 * @returns {CKEDITOR.dom.element} The element instance, or null if not found.
		 * @example
		 * var element = CKEDITOR.document.getById( 'myElement' );
		 * alert( element.getId() );  // "myElement"
		 */
		getById : function( elementId )
		{
			var $ = this.$.getElementById( elementId );
			return $ ? new CKEDITOR.dom.element( $ ) : null;
		},
		getByAddress : function( address, normalized )
		{
			var $ = this.$.documentElement;
			for ( var i = 0 ; $ && i < address.length ; i++ )
			{
				var target = address[ i ];
				if ( !normalized )
				{
					$ = $.childNodes[ target ];
					continue;
				}
				var currentIndex = -1;
				for (var j = 0 ; j < $.childNodes.length ; j++ )
				{
					var candidate = $.childNodes[ j ];
					if ( normalized === true &&
							candidate.nodeType == 3 &&
							candidate.previousSibling &&
							candidate.previousSibling.nodeType == 3 )
					{
						continue;
					}
					currentIndex++;
					if ( currentIndex == target )
					{
						$ = candidate;
						break;
					}
				}
			}
			return $ ? new CKEDITOR.dom.node( $ ) : null;
		},
		getElementsByTag : function( tagName, namespace )
		{
			if ( !( CKEDITOR.env.ie && ! ( document.documentMode > 8 ) ) && namespace )
				tagName = namespace + ':' + tagName;
			return new CKEDITOR.dom.nodeList( this.$.getElementsByTagName( tagName ) );
		},
		/**
		 * Gets the <head> element for this document.
		 * @returns {CKEDITOR.dom.element} The <head> element.
		 * @example
		 * var element = CKEDITOR.document.getHead();
		 * alert( element.getName() );  // "head"
		 */
		getHead : function()
		{
			var head = this.$.getElementsByTagName( 'head' )[0];
			if ( !head )
				head = this.getDocumentElement().append( new CKEDITOR.dom.element( 'head' ), true );
			else
			head = new CKEDITOR.dom.element( head );
			return (
			this.getHead = function()
				{
					return head;
				})();
		},
		/**
		 * Gets the <body> element for this document.
		 * @returns {CKEDITOR.dom.element} The <body> element.
		 * @example
		 * var element = CKEDITOR.document.getBody();
		 * alert( element.getName() );  // "body"
		 */
		getBody : function()
		{
			var body = new CKEDITOR.dom.element( this.$.body );
			return (
			this.getBody = function()
				{
					return body;
				})();
		},
		/**
		 * Gets the DOM document element for this document.
		 * @returns {CKEDITOR.dom.element} The DOM document element.
		 */
		getDocumentElement : function()
		{
			var documentElement = new CKEDITOR.dom.element( this.$.documentElement );
			return (
			this.getDocumentElement = function()
				{
					return documentElement;
				})();
		},
		/**
		 * Gets the window object that holds this document.
		 * @returns {CKEDITOR.dom.window} The window object.
		 */
		getWindow : function()
		{
			var win = new CKEDITOR.dom.window( this.$.parentWindow || this.$.defaultView );
			return (
			this.getWindow = function()
				{
					return win;
				})();
		},
		/**
		 * Defines the document contents through document.write. Note that the
		 * previous document contents will be lost (cleaned).
		 * @since 3.5
		 * @param {String} html The HTML defining the document contents.
		 * @example
		 * document.write(
		 *     '<html>' +
		 *         '<head><title>Sample Doc</title></head>' +
		 *         '<body>Document contents created by code</body>' +
		 *      '</html>' );
		 */
		write : function( html )
		{
			// Don't leave any history log in IE. (#5657)
			this.$.open( 'text/html', 'replace' );
			// Support for custom document.domain in IE.
			CKEDITOR.env.isCustomDomain() &&  ( this.$.domain = document.domain );
			this.$.write( html );
			this.$.close();
		}
	});