////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package flashx.textLayout.conversion 
{
	import flash.system.System;
	
	import flashx.textLayout.TextLayoutVersion;
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.elements.BreakElement;
	import flashx.textLayout.elements.Configuration;
	import flashx.textLayout.elements.ContainerFormattedElement;
	import flashx.textLayout.elements.FlowElement;
	import flashx.textLayout.elements.FlowGroupElement;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.GlobalSettings;
	import flashx.textLayout.elements.IConfiguration;
	import flashx.textLayout.elements.ListElement;
	import flashx.textLayout.elements.ListItemElement;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.ParagraphFormattedElement;
	import flashx.textLayout.elements.SpanElement;
	import flashx.textLayout.elements.TabElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.property.Property;
	import flashx.textLayout.tlf_internal;
	use namespace tlf_internal;

	[ExcludeClass]
	/**
	 * @private  
	 * BaseTextLayoutImporter is a base class for handling the import/export of TextLayout text in the native format.
	 */ 
	internal class BaseTextLayoutImporter extends ConverterBase implements ITextImporter
	{	
		private var _ns:Namespace;		// namespace of expected in imported/exported content
		
		private var _textFlowNamespace:Namespace; // namespace of the TextFlow element against which the namespaces of the following elements are validated
				
		protected var _config:ImportExportConfiguration;
		protected var _textFlowConfiguration:IConfiguration = null;
		protected var _importVersion:uint;
		
		// static private const anyPrintChar:RegExp = /[^\s]/g;
		// Consider only tab, line feed, carriage return, and space as characters used for pretty-printing. 
		// While debatable, this is consistent with what CSS does. 
		static private const anyPrintChar:RegExp = /[^\u0009\u000a\u000d\u0020]/g; 

		public function BaseTextLayoutImporter(nsValue:Namespace, config:ImportExportConfiguration)
		{
			_ns = nsValue;
			_config = config;
		}
		
		tlf_internal override function clear():void
		{
			super.clear();
			_textFlowNamespace = null;
			_impliedPara = null;
		}
		
		/** @copy ITextImporter#importToFlow()
		 */
		public function importToFlow(source:Object):TextFlow
		{
			clear();		// empty results of previous imports
			
			if (throwOnError)
				return importToFlowCanThrow(source);
			
			var rslt:TextFlow = null;
			var savedErrorHandler:Function = Property.errorHandler;
			try
			{
				Property.errorHandler = importPropertyErrorHandler;
				rslt = importToFlowCanThrow(source);
			}
			catch (e:Error)
			{
				reportError(e.toString());
			}
			Property.errorHandler = savedErrorHandler;
			return rslt;
		}
		
		/** @copy ITextImporter#get configuration()
		 */
		public function get configuration():IConfiguration
		{
			return _textFlowConfiguration;
		}
		
		public function set configuration(value:IConfiguration):void
		{
			_textFlowConfiguration = value;
		}

		/** @private */
		protected function importPropertyErrorHandler(p:Property,value:Object):void
		{
			reportError(Property.createErrorString(p,value));
		}
		
		private function importToFlowCanThrow(source:Object):TextFlow
		{
			if (source is String)
				return importFromString(String(source));
			else if (source is XML)
				return importFromXML(XML(source));
			return null;
		}
		
		/** Parse and convert input data.
		 * 
		 * @param source - a string which is in XFL format. String is applied to an XML object then passed
		 * to importFromXML to be processed.  The source must be capable of being cast as an XML
		 * object (E4X). 
		 */
		protected function importFromString(source:String):TextFlow
		{
			var originalSettings:Object = XML.settings();
			try
			{
				XML.ignoreProcessingInstructions = false;		
				XML.ignoreWhitespace = false;
				var xmlTree:XML = new XML(source);				
			}			
			finally
			{
				XML.setSettings(originalSettings);
			}	
			
			var textFlow:TextFlow = importFromXML(xmlTree);
			if (Configuration.playerEnablesArgoFeatures)
				System["disposeXML"](xmlTree);
			return textFlow;
		}
		
		/** Parse and convert input data.
		 * 
		 * xflSource is a XFL formated object which must be capable of being cast as an XML
		 * object (E4X). 
		 */
		protected function importFromXML(xmlSource:XML):TextFlow
			// Parse an XFL hierarchy into a TextFlow, using the geometry supplied by a TextFrame
			// to host child containers (e.g. tables). This is the main entry point into this class.
		{
			return parseContent(xmlSource[0]);
		}
		
		// This routine imports a TextFlow
		protected function parseContent(rootStory:XML):TextFlow
		{
			// If the root element isn't a textFlow we know how to parse, keep descending the hierarchy.
			var child:XML = rootStory..*::TextFlow[0];
			if (child)
				return parseTextFlow(this, rootStory);
			return null;
		}
		
		/** Returns the namespace used in for writing XML/XFL
		 * 
		 * @return the Namespace being used.
		 */
		public function get ns(): Namespace
		{
			return _ns;
		}
		
		// Remove double spaces, tabs, and newlines.
		// If I have a sequence of different sorts of spaces (e.g., en quad, hair space), would I want them converted down to one space? Probably not.
		// For now, u0020 is the only space character we consider for eliminating duplicates, though u00A0 (non-breaking space) is potentially eligible. 
		static private const dblSpacePattern:RegExp = /[\u0020]{2,}/g;
		// Tab, line feed, and carriage return
		static private const tabNewLinePattern:RegExp = /[\u0009\u000a\u000d]/g;
		protected static function stripWhitespace(insertString:String):String
		{
			// Replace the newlines and tabs inside the element with spaces.
			return insertString.replace(tabNewLinePattern, " ");
		}

		/** Parse XML and convert to  TextFlow. 
		 * @param importer		parser object
		 * @param xmlToParse	content to parse
		 * @param parent always null - this parameter is only provided to match FlowElementInfo.importer signature
		 * @return TextFlow	the new TextFlow created as a result of the parse
		 */
		static public function parseTextFlow(importer:BaseTextLayoutImporter, xmlToParse:XML, parent:Object=null):TextFlow
		{
			return importer.createTextFlowFromXML(xmlToParse, null);
		}		
		
		/** Static method to parse the supplied XML into a paragrph. Parse the <p ...> tag and it's children.
		 * 
		 * @param importer	parser object
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the new content
		 */
		static public function parsePara(importer:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var paraElem:ParagraphElement = importer.createParagraphFromXML(xmlToParse);
			if (importer.addChild(parent, paraElem))
			{
				importer.parseFlowGroupElementChildren(xmlToParse, paraElem);
				//if parsing an empty paragraph, create a Span for it.
				if (paraElem.numChildren == 0)
					paraElem.addChild(new SpanElement());
			}
		}
		
		static protected function copyAllStyleProps(dst:FlowLeafElement,src:FlowLeafElement):void
		{
			dst.format = src.format;
			dst.typeName	= src.typeName;
			dst.id          = src.id;
		}
		
		/** Static method for constructing a span from XML. Parse the <span> ... </span> tag. 
		 * Insert the span into its parent
		 * 
		 * @param importer	parser object
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the new content
		 */
		static public function parseSpan(importer:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var firstSpan:SpanElement = importer.createSpanFromXML(xmlToParse);
			
			var elemList:XMLList = xmlToParse[0].children();
			if(elemList.length() == 0)
			{
				// Empty span, but may have formatting, so don't strip it out. 
				// Note: the normalizer may yet strip it out if it is not the last child, but that's the normalizer's business.
				importer.addChild(parent, firstSpan); 
				return;
			}
	
			for each (var child:XML in elemList) 
			{
				var elemName:String = child.name() ? child.name().localName : null;
					
				if (elemName == null) // span text
				{
					if (firstSpan.parent == null)	// hasn't been used yet
					{
						firstSpan.text = child.toString();
						importer.addChild(parent, firstSpan);
					}
					else
					{
						var s:SpanElement = new SpanElement();	// No PMD
						copyAllStyleProps(s,firstSpan);
						s.text = child.toString();
						importer.addChild(parent, s);
					}
				}
				else if (elemName == "br")
				{
					var brElem:BreakElement = importer.createBreakFromXML(child);	// may be null
					if (brElem)
					{
						copyAllStyleProps(brElem,firstSpan);
						importer.addChild(parent, brElem);
					}
					else
						importer.reportError(GlobalSettings.resourceStringFunction("unexpectedXMLElementInSpan",[ elemName ]));
				}
				else if (elemName == "tab")
				{
					var tabElem:TabElement = importer.createTabFromXML(child);	// may be null
					if (tabElem)
					{
						copyAllStyleProps(tabElem,firstSpan);
						importer.addChild(parent, tabElem);
					}
					else
						importer.reportError(GlobalSettings.resourceStringFunction("unexpectedXMLElementInSpan",[ elemName ]));
				}
				else
					importer.reportError(GlobalSettings.resourceStringFunction("unexpectedXMLElementInSpan",[ elemName ]));				
			}
		}
		
		/** Static method for constructing a break element from XML. Validate the <br> ... </br> tag. 
		 * Use "\u2028" as the text; Insert the new element into its parent 
		 * 
		 * @param importer	parser object
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the new content
		 */
		static public function parseBreak(importer:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var breakElem:BreakElement = importer.createBreakFromXML(xmlToParse);
			importer.addChild(parent, breakElem);
		}

		
		/** Static method for constructing a tab element from XML. Validate the <tab> ... </tab> tag. 
		 * Use "\t" as the text; Insert the new element into its parent 
		 * 
		 * @param importer	parser object
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the new content
		 */
		static public function parseTab(importer:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var tabElem:TabElement = importer.createTabFromXML(xmlToParse);	// may be null
			if (tabElem)
				importer.addChild(parent, tabElem);
		}

		static public function parseList(importer:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var listElem:ListElement = importer.createListFromXML(xmlToParse);
			if (importer.addChild(parent, listElem))
			{
				importer.parseFlowGroupElementChildren(xmlToParse, listElem);
			}
		}

		static public function parseListItem(importer:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var listItem:ListItemElement = importer.createListItemFromXML(xmlToParse);
			if (importer.addChild(parent, listItem))
			{
				importer.parseFlowGroupElementChildren(xmlToParse, listItem);
				//if parsing an empty list item, create a Paragraph for it.
				if (listItem.numChildren == 0)
					listItem.addChild(new ParagraphElement());	
			}
		}
		
		protected function checkNamespace(xmlToParse:XML):Boolean
		{
			var elementNS:Namespace = xmlToParse.namespace();
			if (!_textFlowNamespace) // Not set yet; must be parsing the TextFlow element
			{
				// TextFlow element: allow only empty namespace and flow namespace
				if (elementNS != ns) 
				{
					reportError(GlobalSettings.resourceStringFunction("unexpectedNamespace", [elementNS.toString()]));
					return false;
				}
				_textFlowNamespace = elementNS;
			}
			// Other elements: must match the namespace of the TextFlow element
			// Specifically, can't be empty unless the TextFlow element's namespace is also empty 
			else if (elementNS != _textFlowNamespace) 
			{
				reportError(GlobalSettings.resourceStringFunction("unexpectedNamespace", [elementNS.toString()]));
				return false;
			}
			
			return true;
		}
		
		public function parseAttributes(xmlToParse:XML,formatImporters:Array):void
		{
			var importer:IFormatImporter;
			// reset them all
			for each (importer in formatImporters)
				importer.reset();
				
			if (!xmlToParse)
				return;
			
			for each (var item:XML in xmlToParse.attributes())
			{
				var propertyName:String = item.name().localName;
				var propertyValue:String = item.toString();
				var imported:Boolean = false;
				
				// Strip out padding properties from XML coming in before TLF 2.0, since they were ignored but are no longer. This preserves the look of the text.
				if (xmlToParse.localName() == "TextFlow")
				{
					if (propertyName == "version")	// skip over the version attribute, we've already processed it
						continue;
				}
				else if (_importVersion < TextLayoutVersion.VERSION_2_0 &&
					 (propertyName == "paddingLeft" || propertyName == "paddingTop" || propertyName == "paddingRight" || propertyName == "paddingBottom"))
					continue;
				for each (importer in formatImporters)
				{
					if (importer.importOneFormat(propertyName,propertyValue))
					{
						imported = true;
						break;
					}
				}
				if (!imported)	// not a supported attribute
					handleUnknownAttribute (xmlToParse.name().localName, propertyName);
			}
		}
				
		static protected function extractAttributesHelper(curAttrs:Object, importer:TLFormatImporter):Object
		{
			if (curAttrs == null)
				return importer.result;
			
			if (importer.result == null)
				return curAttrs;
				
			var workAttrs:Object = new importer.classType(curAttrs);
			workAttrs.apply(importer.result);
			return workAttrs;
		}	
		
		/** Parse XML and convert to  TextFlow.
		 * @param xmlToParse	content to parse
		 * @param textFlow 		TextFlow we're parsing. If null, create or find a new TextFlow based on XML content
		 * @return TextFlow	the new TextFlow created as a result of the parse
		 */
		public function createTextFlowFromXML(xmlToParse:XML, newFlow:TextFlow = null):TextFlow	// No PMD
		{
			CONFIG::debug { assert(false,"missing override for createTextFlowFromXML"); }
			return null;
		}
		
		public function createParagraphFromXML(xmlToParse:XML):ParagraphElement	// No PMD
		{
			CONFIG::debug { assert(false,"missing override for createParagraphFromXML"); }
			return null;
		}
		
		public function createSpanFromXML(xmlToParse:XML):SpanElement	// No PMD
		{
			CONFIG::debug { assert(false,"missing override for createSpanFromXML"); }
			return null;
		}
		
		public function createBreakFromXML(xmlToParse:XML):BreakElement
		{
			parseAttributes(xmlToParse,null);	// no attributes allowed - reports errors
			return new BreakElement();
		}
		
		public function createListFromXML(xmlToParse:XML):ListElement	// No PMD
		{
			CONFIG::debug { assert(false,"missing override for createListFromXML"); }
			return null;
		}

		public function createListItemFromXML(xmlToParse:XML):ListItemElement	// No PMD
		{
			CONFIG::debug { assert(false,"missing override for createListItemFromXML"); }
			return null;
		}
		
		public function createTabFromXML(xmlToParse:XML):TabElement
		{
			parseAttributes(xmlToParse,null);	// reports errors
			return new TabElement();
		}
		
		/** Parse XML, convert to FlowElements and add to the parent.
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the new content
		 */
		public function parseFlowChildren(xmlToParse:XML, parent:FlowGroupElement):void
		{
			parseFlowGroupElementChildren(xmlToParse, parent);
		}
		
		/** Parse XML, convert to FlowElements and add to the parent.
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the new content
		 * @param chainedParent whether parent actually corresponds to xmlToParse or has been chained (such as when xmlToParse is a formatting element) 
		 */
		public function parseFlowGroupElementChildren(xmlToParse:XML, parent:FlowGroupElement, exceptionElements:Object = null, chainedParent:Boolean=false):void
		{
			for each (var child:XML in xmlToParse.children())
			{
				if (child.nodeKind() == "element")
				{
					parseObject(child.name().localName, child, parent, exceptionElements);
				}
				// look for mixed content here
 				else if (child.nodeKind() == "text") 
 				{
 					var txt:String = child.toString();
 					// Strip whitespace-only text appearing as a child of a container-formatted element
 					var strip:Boolean = false;
 					if (parent is ContainerFormattedElement)
 					{
						strip = txt.search(anyPrintChar) == -1;
					}
					
 					if (!strip) 
						addChild(parent, createImpliedSpan(txt));
				}
			}
			
			// no implied paragraph should extend across container elements
			if (!chainedParent && parent is ContainerFormattedElement)
				resetImpliedPara();
		}
		
		/** create an implied span with specified text */
		public function createImpliedSpan(text:String):SpanElement
		{
			var span:SpanElement = new SpanElement();	// No PMD
			span.text = text;
			return span;
		}
			
		public function createParagraphFlowFromXML(xmlToParse:XML, newFlow:TextFlow = null):TextFlow	// No PMD
		{
			CONFIG::debug { assert(false,"missing override for createParagraphFlowFromXML"); }	// client must override
			return null;
		}
		
		tlf_internal function parseObject(name:String, xmlToParse:XML, parent:FlowGroupElement, exceptionElements:Object=null):void
		{
			if (!checkNamespace(xmlToParse))
				return;

			var info:FlowElementInfo = _config.lookup(name);
			if (!info)
			{
				if (exceptionElements == null || exceptionElements[name] === undefined)
					handleUnknownElement (name, xmlToParse, parent);		
			}
			else
				info.parser(this, xmlToParse, parent);
		}
		
		protected function handleUnknownElement(name:String, xmlToParse:XML, parent:FlowGroupElement):void
		{
			reportError(GlobalSettings.resourceStringFunction("unknownElement", [ name ]));	
		}
		
		protected function handleUnknownAttribute(elementName:String, propertyName:String):void
		{
			reportError(GlobalSettings.resourceStringFunction("unknownAttribute", [ propertyName, elementName ]));	
		}
		
		protected function getElementInfo(xmlToParse:XML):FlowElementInfo
		{
			return _config.lookup(xmlToParse.name().localName);
		}
		
		protected function GetClass(xmlToParse:XML):Class
		{
			var info:FlowElementInfo = _config.lookup(xmlToParse.name().localName);
			return info ? info.flowClass : null;
		}
		
		// In the text model, non-FlowParagraphElements (i.e. spans, images, links, TCY) cannot be children of a ContainerElement (TextFlow, Div etc.)
		// They can only be children of paragraphs or subparagraph blocks. 
		// In XML, however, <p> elements can be implied (for example, a <span> may appear as a direct child of <flow>).  
		// So, while parsing the XML, if we enounter a non-FlowParagraphElement child of a ContainerElement 
		// 1. an explicitly created paragraph is used as the parent instead
		// 2. such explicitly created paragraphs are shared by adjacent flow elements provided there isn't an intervening FlowParagraphElement		
		private var _impliedPara:ParagraphElement = null; 
		
		/** @private */
		tlf_internal function createImpliedParagraph():ParagraphElement
		{
			return createParagraphFromXML(<p/>);
		}
		
		/**
		 * @private
		 * Helper function for adding a child flow element that honors throwOnError setting and uses the parent override
		 * NOTE: You MUST NOT call addChild directly unless you are sure
		 * - There is not possibility of an implied paragraph, and
		 * - Parent is of type that can contain child
		*/
		tlf_internal function addChild(parent:FlowGroupElement, child:FlowElement):Boolean
		{
			if (child is ParagraphFormattedElement)
			{
				// Reset due to possibly intervening FlowParagrahElement; See note 2. above
				resetImpliedPara();
			}
			else if (parent is ContainerFormattedElement)
			{
				// See note 1. above
				if (!_impliedPara)
				{
					// Derived classes may have special behavior for <p> tags. Implied paragraphs may need the same behavior.
					// So call createParagraphFromXML, don't just instantiate a ParagraphElement 
					_impliedPara = createImpliedParagraph();
					parent.addChild(_impliedPara);
				}
				
				parent = _impliedPara;
			}	
			
			if (throwOnError)
				parent.addChild(child);
			else
			{
				try
				{
					parent.addChild(child);
				}
				catch (e:*)
				{
					reportError(e); 	
					return false;
				}
			}
			
			return true;
		} 
		
		tlf_internal function resetImpliedPara():void
		{
			if (_impliedPara)
			{
				onResetImpliedPara(_impliedPara);
				_impliedPara = null;
			}
		}
		
		protected function onResetImpliedPara(para:ParagraphElement):void
		{
		}
	}
}

