/*
 *
 *  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 org.apache.royale.compiler.internal.codegen.js.jx;

import java.util.*;

import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.common.ASModifier;
import org.apache.royale.compiler.common.ModifiersSet;
import org.apache.royale.compiler.constants.IASKeywordConstants;
import org.apache.royale.compiler.definitions.*;
import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSessionModel.BindableVarInfo;
import org.apache.royale.compiler.internal.codegen.js.JSSessionModel.ImplicitBindableImplementation;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils;
import org.apache.royale.compiler.internal.definitions.ClassDefinition;
import org.apache.royale.compiler.internal.driver.js.goog.JSGoogConfiguration;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.tree.as.FunctionNode;
import org.apache.royale.compiler.internal.tree.as.NamespaceIdentifierNode;
import org.apache.royale.compiler.internal.tree.as.SetterNode;
import org.apache.royale.compiler.internal.tree.as.VariableNode;
import org.apache.royale.compiler.problems.UnknownTypeProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.scopes.IASScope;
import org.apache.royale.compiler.scopes.IDefinitionSet;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.tree.metadata.IMetaTagNode;
import org.apache.royale.compiler.tree.metadata.IMetaTagsNode;

public class PackageFooterEmitter extends JSSubEmitter implements
        ISubEmitter<IPackageDefinition>
{

    public PackageFooterEmitter(IJSEmitter emitter)
    {
        super(emitter);
    }

    @Override
    public void emit(IPackageDefinition definition)
    {
        IASScope containedScope = definition.getContainedScope();
        ITypeDefinition type = EmitterUtils.findType(containedScope
                .getAllLocalDefinitions());
        if (type == null)
            return;

        getEmitter().emitSourceMapDirective(type.getNode());
    }

    public void emitClassInfo(ITypeNode tnode)
    {
        JSRoyaleDocEmitter doc = (JSRoyaleDocEmitter) getEmitter()
        .getDocEmitter();

	    if (!getEmitter().getModel().isExterns && doc.getEmitExports())
	    {
			boolean isInterface = tnode instanceof IInterfaceNode;
			boolean isDynamic = tnode instanceof IClassNode && tnode.hasModifier(ASModifier.DYNAMIC);
			/*
		     * Metadata
		     *
		     * @type {Object.<string, Array.<Object>>}
		     */
		    writeNewline();
		    writeNewline();
		    writeNewline();
		    doc.begin();
		    writeNewline(" * Metadata");
		    writeNewline(" *");
		    writeNewline(" * @type {Object.<string, Array.<Object>>}");
		    doc.end();
	
		    // a.B.prototype.AFJS_CLASS_INFO = {  };
		    write(getEmitter().formatQualifiedName(tnode.getQualifiedName()));
		    write(ASEmitterTokens.MEMBER_ACCESS);
		    write(JSEmitterTokens.PROTOTYPE);
		    write(ASEmitterTokens.MEMBER_ACCESS);
		    writeToken(JSRoyaleEmitterTokens.ROYALE_CLASS_INFO);
		    writeToken(ASEmitterTokens.EQUAL);
		    writeToken(ASEmitterTokens.BLOCK_OPEN);
		
		    // names: [{ name: '', qName: '', kind:'interface|class' }]
		    write(JSRoyaleEmitterTokens.NAMES);
		    writeToken(ASEmitterTokens.COLON);
		    write(ASEmitterTokens.SQUARE_OPEN);
		    writeToken(ASEmitterTokens.BLOCK_OPEN);
		    write(JSRoyaleEmitterTokens.NAME);
		    writeToken(ASEmitterTokens.COLON);
		    write(ASEmitterTokens.SINGLE_QUOTE);
		    write(tnode.getName());
		    write(ASEmitterTokens.SINGLE_QUOTE);
		    writeToken(ASEmitterTokens.COMMA);
		    write(JSRoyaleEmitterTokens.QNAME);
		    writeToken(ASEmitterTokens.COLON);
		    write(ASEmitterTokens.SINGLE_QUOTE);
		    write(getEmitter().formatQualifiedName(tnode.getQualifiedName()));
		    write(ASEmitterTokens.SINGLE_QUOTE);
			writeToken(ASEmitterTokens.COMMA);
			write(JSRoyaleEmitterTokens.ROYALE_CLASS_INFO_KIND);
			writeToken(ASEmitterTokens.COLON);
			write(ASEmitterTokens.SINGLE_QUOTE);
			if (isInterface) write(JSRoyaleEmitterTokens.ROYALE_CLASS_INFO_INTERFACE_KIND);
			else write(JSRoyaleEmitterTokens.ROYALE_CLASS_INFO_CLASS_KIND);
			//writeToken(ASEmitterTokens.SINGLE_QUOTE);
			
			if (isDynamic) {
				//only add the 'isDynamic' tag when it is needed
				write(ASEmitterTokens.SINGLE_QUOTE);
				writeToken(ASEmitterTokens.COMMA);
				write(JSRoyaleEmitterTokens.ROYALE_CLASS_INFO_IS_DYNAMIC);
				writeToken(ASEmitterTokens.COLON);
				write(ASEmitterTokens.TRUE);
			} else {
				writeToken(ASEmitterTokens.SINGLE_QUOTE);
			}
			
		    write(ASEmitterTokens.BLOCK_CLOSE);
		    write(ASEmitterTokens.SQUARE_CLOSE);
	
		    IExpressionNode[] enodes;
		    if (tnode instanceof IClassNode)
		        enodes = ((IClassNode) tnode).getImplementedInterfaceNodes();
		    else {
				enodes = ((IInterfaceNode) tnode).getExtendedInterfaceNodes();
			}
	
	
			boolean needsIEventDispatcher = tnode instanceof IClassNode
					&& ((IClassDefinition) tnode.getDefinition()).needsEventDispatcher(getProject())
					&& getModel().getImplicitBindableImplementation() == ImplicitBindableImplementation.IMPLEMENTS;
	
			//we can remove the mapping from the model for ImplicitBindableImplementation now
			if (tnode.getDefinition() instanceof IClassDefinition)
					getModel().unregisterImplicitBindableImplementation(
							(IClassDefinition) tnode.getDefinition());
	
		    if (enodes.length > 0 || needsIEventDispatcher)
		    {
		        writeToken(ASEmitterTokens.COMMA);
		
		        // interfaces: [a.IC, a.ID]
		        write(JSRoyaleEmitterTokens.INTERFACES);
		        writeToken(ASEmitterTokens.COLON);
		        write(ASEmitterTokens.SQUARE_OPEN);
				if (needsIEventDispatcher) {
					//add IEventDispatcher interface to implemented interfaces list
					write(getEmitter().formatQualifiedName(BindableEmitter.DISPATCHER_INTERFACE_QNAME));
					if (enodes.length > 0)
						writeToken(ASEmitterTokens.COMMA);
				}
		        int i = 0;
		        for (IExpressionNode enode : enodes)
		        {
		        	IDefinition edef = enode.resolve(getProject());
		        	if (edef == null)
		        		continue;
		            write(getEmitter().formatQualifiedName(
		                    edef.getQualifiedName()));
		            if (i < enodes.length - 1)
		                writeToken(ASEmitterTokens.COMMA);
		            i++;
		        }
		        write(ASEmitterTokens.SQUARE_CLOSE);
		    }
		    write(ASEmitterTokens.SPACE);
		    write(ASEmitterTokens.BLOCK_CLOSE);
		    write(ASEmitterTokens.SEMICOLON);

		    if (needsIEventDispatcher) {
				JSRoyaleEmitter fjs = (JSRoyaleEmitter)getEmitter();
				fjs.getBindableEmitter().emitBindableInterfaceMethods(((IClassDefinition) tnode.getDefinition()));
			}

		    collectReflectionData(tnode);
		    IMetaTagNode[] metadata = null;
		    IMetaTagsNode metadataTags = tnode.getMetaTags();
		    if (metadataTags != null)
		    	metadata = metadataTags.getAllTags();
	
			String typeName = getEmitter().formatQualifiedName(tnode.getQualifiedName());
	
			emitReflectionData(
					typeName,
					reflectionKind,
					varData,
					accessorData,
					methodData,
					metadata);
			
		    if (!isInterface) {
		    	emitReflectionRegisterInitialStaticFields(typeName, (ClassDefinition) tnode.getDefinition());
			}
		   
		    emitExportProperties(typeName, exportProperties, exportSymbols);
	    }
    }

    public enum ReflectionKind{
		CLASS,
		INTERFACE
	}
    
    public class VariableData
    {
    	public String name;
		public String customNS = null;
    	public String type;
		public Boolean isStatic = false;
    	public IMetaTagNode[] metaData;
    }
    
    public class MethodData
    {
    	public String name;
		public String customNS = null;
    	public String type;
		public Boolean isStatic = false;
    	public String declaredBy;
		public IParameterNode [] parameters;
    	public IMetaTagNode[] metaData;
    }

	public class AccessorData extends MethodData
	{
		public String access;
	}

	private ArrayList<VariableData> varData;
    private ArrayList<AccessorData> accessorData;
    private ArrayList<MethodData> methodData;
	private ReflectionKind reflectionKind;
    private ArrayList<String> exportProperties;
    private ArrayList<String> exportSymbols;
    
    public void collectReflectionData(ITypeNode tnode)
    {
    	JSRoyaleEmitter fjs = (JSRoyaleEmitter)getEmitter();
    	exportProperties = new ArrayList<String>();
    	exportSymbols = new ArrayList<String>();
		ICompilerProject project = getWalker().getProject();
    	Set<String> exportMetadata = Collections.<String> emptySet();
    	if (project instanceof RoyaleJSProject)
    	{
    		RoyaleJSProject fjsp = ((RoyaleJSProject)project);
    		if (fjsp.config != null)
    			exportMetadata = fjsp.config.getCompilerKeepCodeWithMetadata();
    	}
    	varData = new ArrayList<VariableData>();
    	accessorData = new ArrayList<AccessorData>();
    	methodData = new ArrayList<MethodData>();
    	/*
	     * Reflection
	     *
	     * @return {Object.<string, Function>}
	     */
        IDefinitionNode[] dnodes;
		String name;
		//bindables:
		HashMap<String, BindableVarInfo> bindableVars = getModel().getBindableVars();
        boolean isInterface = tnode instanceof IInterfaceNode;
	    if (!isInterface)
	        dnodes = ((IClassNode) tnode).getAllMemberNodes();
	    else
	        dnodes = ((IInterfaceNode) tnode).getAllMemberDefinitionNodes();
		reflectionKind = isInterface ? ReflectionKind.INTERFACE : ReflectionKind.CLASS;

        for (IDefinitionNode dnode : dnodes)
        {
            ModifiersSet modifierSet = dnode.getDefinition().getModifiers();
            boolean isStatic = (modifierSet != null && modifierSet
                    .hasModifier(ASModifier.STATIC));
            if ((dnode.getNodeID() == ASTNodeID.VariableID ||
            		dnode.getNodeID() == ASTNodeID.BindableVariableID))
            {
            	IVariableNode varNode = (IVariableNode)dnode;
                String ns = varNode.getNamespace();
				boolean isConst = varNode.isConst();
				if (isConst) {
					//todo consider outputting consts, none output for now
					continue;
				}
				//explicit exclusion from reflection data:
				if (getModel().suppressedExportNodes.contains(varNode)) {
					continue;
				}
				String altNS = null;
				if (ns != null &&  EmitterUtils.isCustomNamespace(ns)) {
					altNS = ((INamespaceDefinition)(((VariableNode) varNode).getNamespaceNode().resolve(getProject()))).getURI();
				}
                if (isInterface || (ns != null && ns.equals(IASKeywordConstants.PUBLIC )) || altNS != null)
                {
                	name = varNode.getName();

					IMetaTagsNode metaData = varNode.getMetaTags();
					//first deal with 'Bindable' upgrades to getters/setters
					if (!isInterface && bindableVars.containsKey(name)
							&& bindableVars.get(name).namespace.equals(IASKeywordConstants.PUBLIC)) {

						AccessorData bindableAccessor = new AccessorData();
						bindableAccessor.customNS = altNS;
						bindableAccessor.name = name;
						bindableAccessor.access = "readwrite";
						bindableAccessor.type = bindableVars.get(name).type;
						bindableAccessor.declaredBy = fjs.formatQualifiedName(tnode.getQualifiedName(), true);
						bindableAccessor.isStatic = isStatic;
						//attribute the metadata from the var definition to the Bindable Accessor implementation
						if (metaData != null)
						{
							IMetaTagNode[] tags = metaData.getAllTags();
							if (tags.length > 0)
								bindableAccessor.metaData = tags;
						}
						accessorData.add(bindableAccessor);
						//skip processing this varNode as a variable, it has now be added as an accessor
						continue;
					}


                	VariableData data = new VariableData();
                	varData.add(data);
                	data.name = name;
                	data.customNS = altNS;
					data.isStatic = isStatic;
					String qualifiedTypeName =	varNode.getVariableTypeNode().resolveType(getProject()).getQualifiedName();
					data.type = fjs.formatQualifiedName(qualifiedTypeName, true);

            	    if (metaData != null)
            	    {
            	    	IMetaTagNode[] tags = metaData.getAllTags();
            	    	if (tags.length > 0)
            	    	{
            	    		data.metaData = tags;
            	    		for (IMetaTagNode tag : tags)
            	    		{
            	    			String tagName =  tag.getTagName();
            	    			if (exportMetadata.contains(tagName))
            	    			{
            	    				if (data.isStatic)
            	    					exportSymbols.add(data.name);
            	    				else
                	    				exportProperties.add(data.name);
            	    			}
            	    		}
            	    	}
            	    }
                }
            }
        }

        if (getModel().hasStaticBindableVars()) {
			//we have an implicit implementation of a static event dispatcher
			//so add the 'staticEventDispatcher' accessor to the reflection data
			AccessorData staticEventDispatcher = new AccessorData();
			staticEventDispatcher.name = BindableEmitter.STATIC_DISPATCHER_GETTER;
			staticEventDispatcher.access = "readonly";
			staticEventDispatcher.type = fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME, true);
			staticEventDispatcher.declaredBy = fjs.formatQualifiedName(tnode.getQualifiedName(), true);
			staticEventDispatcher.isStatic = true;
			accessorData.add(staticEventDispatcher);
		}
     
	    HashMap<String, AccessorData> instanceAccessorMap = new HashMap<String, AccessorData>();
		HashMap<String, AccessorData> staticAccessorMap = new HashMap<String, AccessorData>();
        for (IDefinitionNode dnode : dnodes)
        {
            ModifiersSet modifierSet = dnode.getDefinition().getModifiers();
            boolean isStatic = (modifierSet != null && modifierSet
                    .hasModifier(ASModifier.STATIC));

			HashMap<String, AccessorData> accessorMap = isStatic ? staticAccessorMap : instanceAccessorMap;
            if ((dnode.getNodeID() == ASTNodeID.GetterID ||
            		dnode.getNodeID() == ASTNodeID.SetterID))
            {
            	IFunctionNode fnNode = (IFunctionNode)dnode;
                String ns = fnNode.getNamespace();
                boolean suppressed = getModel().suppressedExportNodes.contains(fnNode);
	
				String altNS = null;
				if (ns != null &&  EmitterUtils.isCustomNamespace(ns)) {
					altNS = ((INamespaceDefinition)(((FunctionNode) fnNode).getNamespaceNode().resolve(getProject()))).getURI();
				}

                if (isInterface || (ns != null && ns.equals(IASKeywordConstants.PUBLIC)) || altNS != null)
                {
					String accessorName = fnNode.getName();
					String nameKey = altNS!=null? altNS+accessorName : accessorName;
                	AccessorData data = accessorMap.get(nameKey);
					if (data == null) {
						if (suppressed) continue;
						data = new AccessorData();
					} else {
						if (suppressed) {
							accessorData.remove(data);
							accessorMap.remove(nameKey);
							continue;
						}
					}
                	data.name = accessorName;
					data.customNS = altNS;
                	if (!accessorData.contains(data)) accessorData.add(data);
            	    if (dnode.getNodeID() == ASTNodeID.GetterID) {
						data.type = fnNode.getReturnTypeNode().resolveType(getProject()).getQualifiedName();
						if (data.access == null) {
							data.access = "readonly";
						} else data.access = "readwrite";
					}
            	    else {
						data.type = ((SetterNode)fnNode).getVariableTypeNode().resolveType(getProject()).getQualifiedName();
						if (data.access == null) {
							data.access = "writeonly";
						} else data.access = "readwrite";
					}
                	accessorMap.put(nameKey, data);
            	    data.type = fjs.formatQualifiedName(data.type, true);
            	    IClassNode declarer = (IClassNode)fnNode.getAncestorOfType(IClassNode.class);
            	    String declarant = fjs.formatQualifiedName(tnode.getQualifiedName(), true);
            	    if (declarer != null)
            	    	declarant = fjs.formatQualifiedName(declarer.getQualifiedName(), true);
            	    data.declaredBy = declarant;
					data.isStatic = isStatic;
            	    IMetaTagsNode metaData = fnNode.getMetaTags();
            	    if (metaData != null)
            	    {
            	    	IMetaTagNode[] tags = metaData.getAllTags();
            	    	if (tags.length > 0)
            	    	{
            	    		data.metaData = tags;
        	    			/* accessors don't need exportProp since they are referenced via the defineProp data structure
            	    		for (IMetaTagNode tag : tags)
            	    		{
            	    			String tagName =  tag.getTagName();
            	    			if (exportMetadata.contains(tagName))
            	    			{
            	    				if (data.isStatic)
            	    					exportSymbols.add(data.name);
            	    				else
                	    				exportProperties.add(data.name);
            	    			}
            	    		}
            	    		*/
            	    	}
            	    }
                }
            }
        }
        for (IDefinitionNode dnode : dnodes)
        {
            ModifiersSet modifierSet = dnode.getDefinition().getModifiers();
            boolean isStatic = (modifierSet != null && modifierSet
                    .hasModifier(ASModifier.STATIC));
            if (dnode.getNodeID() == ASTNodeID.FunctionID )
            {
            	IFunctionNode fnNode = (IFunctionNode)dnode;
                String ns = fnNode.getNamespace();
	
				String altNS = null;
				if (ns != null && EmitterUtils.isCustomNamespace(ns)) {
					altNS = ((INamespaceDefinition)(((FunctionNode) fnNode).getNamespaceNode().resolve(getProject()))).getURI();
				}
                
                if (isInterface || (ns != null && ns.equals(IASKeywordConstants.PUBLIC)) || altNS != null)
                {
                	if (getModel().suppressedExportNodes.contains(fnNode)) continue;
                	MethodData data = new MethodData();
					data.isStatic = isStatic;
                	methodData.add(data);
                	data.name = fnNode.getName();
                	data.customNS = altNS;
					String qualifiedTypeName =	fnNode.getReturnType();
					if (!(qualifiedTypeName.equals("") || qualifiedTypeName.equals("void"))) {
							qualifiedTypeName = fnNode.getReturnTypeNode().resolveType(getProject()).getQualifiedName();
					}
					data.type = fjs.formatQualifiedName(qualifiedTypeName, true);
            	    ITypeNode declarer;
            	    if (isInterface)
            	    	declarer = (IInterfaceNode)fnNode.getAncestorOfType(IInterfaceNode.class);
            	    else
            	    	declarer = (IClassNode)fnNode.getAncestorOfType(IClassNode.class);
            	    String declarant = fjs.formatQualifiedName(tnode.getQualifiedName(), true);
            	    if (declarer != null)
            	    	declarant = fjs.formatQualifiedName(declarer.getQualifiedName(), true);
            	    data.declaredBy = declarant;
            	    IMetaTagsNode metaData = fnNode.getMetaTags();
            	    if (metaData != null)
            	    {
            	    	IMetaTagNode[] tags = metaData.getAllTags();
            	    	if (tags.length > 0)
            	    	{
            	    		data.metaData = tags;
            	    		for (IMetaTagNode tag : tags)
            	    		{
            	    			String tagName =  tag.getTagName();
            	    			if (exportMetadata.contains(tagName))
            	    			{
            	    				if (data.isStatic)
            	    					exportSymbols.add(data.name);
            	    				else
                	    				exportProperties.add(data.name);
            	    			}
            	    		}
            	    	}
            	    }
					IParameterNode[] paramNodes = fnNode.getParameterNodes();
					if (paramNodes != null) {
						data.parameters = paramNodes;
					}
				}
            }
        }
    }




    private void emitReflectionDataStart(String typeName) {
		JSRoyaleDocEmitter doc = (JSRoyaleDocEmitter) getEmitter()
				.getDocEmitter();
	    /*
	     * Reflection
	     *
	     * @return {Object.<string, Function>}
	     */

		writeNewline();
		writeNewline();
		writeNewline();
		writeNewline();
		doc.begin();
		writeNewline(" * Reflection");
		writeNewline(" *");
		writeNewline(" * @return {Object.<string, Function>}");
		doc.end();

		// a.B.prototype.ROYALE_REFLECTION_INFO = function() {
		write(typeName);
		write(ASEmitterTokens.MEMBER_ACCESS);
		write(JSEmitterTokens.PROTOTYPE);
		write(ASEmitterTokens.MEMBER_ACCESS);
		writeToken(JSRoyaleEmitterTokens.ROYALE_REFLECTION_INFO);
		writeToken(ASEmitterTokens.EQUAL);
		writeToken(ASEmitterTokens.FUNCTION);
		write(ASEmitterTokens.PAREN_OPEN);
		writeToken(ASEmitterTokens.PAREN_CLOSE);
		write(ASEmitterTokens.BLOCK_OPEN);

		indentPush();
		writeNewline();
		// return {
		writeToken(ASEmitterTokens.RETURN);
		write(ASEmitterTokens.BLOCK_OPEN);
	}

	private void emitReflectionDataEnd(String typeName, boolean hasContent) {
		JSGoogConfiguration config = ((RoyaleJSProject)getWalker().getProject()).config;
		
		if (hasContent) writeNewline();
		// close return object
		write(ASEmitterTokens.BLOCK_CLOSE);
		write(ASEmitterTokens.SEMICOLON);

		// close function
		indentPop();
		writeNewline();
		write(ASEmitterTokens.BLOCK_CLOSE);
		writeNewline(ASEmitterTokens.SEMICOLON);
		
		if (config == null) return;
		//add compiletime descriptor flags
		//allow dead-code elimination if reflection is not used
		//doc emitter-ish:
		writeNewline("/**");
		writeNewline(" * @const");
		writeNewline(" * @type {number}");
		writeNewline(" */");
		
		//{typeName}.prototype.ROYALE_COMPILE_FLAGS = {int value here};
		write(typeName);
		write(ASEmitterTokens.MEMBER_ACCESS);
		write(JSEmitterTokens.PROTOTYPE);
		write(ASEmitterTokens.MEMBER_ACCESS);
		writeToken(JSRoyaleEmitterTokens.ROYALE_REFLECTION_INFO_COMPILE_TIME_FLAGS);
		writeToken(ASEmitterTokens.EQUAL);
		//
		write(String.valueOf(config.getReflectionFlags()));
		writeNewline(ASEmitterTokens.SEMICOLON);
	}
    
    public void emitReflectionData(
			String typeName,
			ReflectionKind outputType,
    		List<VariableData> varData,
    		List<AccessorData> accessorData,
    		List<MethodData> methodData,
    		IMetaTagNode[] metaData
    		)
    {

		emitReflectionDataStart(typeName);
		boolean indented = false;
		boolean continueContent = false;
		int count;
		if (outputType == ReflectionKind.CLASS) {
			
			if (varData.size() > 0) {
				indentPush();
				writeNewline();
				indented = true;
				write("variables");
				writeToken(ASEmitterTokens.COLON);
				writeToken(ASEmitterTokens.FUNCTION);
				write(ASEmitterTokens.PAREN_OPEN);
				writeToken(ASEmitterTokens.PAREN_CLOSE);
				write(ASEmitterTokens.BLOCK_OPEN);

				indentPush();
				writeNewline();
				// return {
				writeToken(ASEmitterTokens.RETURN);
				write(ASEmitterTokens.BLOCK_OPEN);
				indentPush();

				count = 0;
				for (VariableData var : varData) {
					if (count > 0)
						write(ASEmitterTokens.COMMA);
					writeNewline();
					count++;
					// varname: { type: typename
					write(ASEmitterTokens.SINGLE_QUOTE);
					//prefix static var names with |
					if (var.isStatic) {
					    write("|");
                    }
					if (var.customNS != null) {
						write(var.customNS);
						write("::");
					}
					write(var.name);
					write(ASEmitterTokens.SINGLE_QUOTE);
					writeToken(ASEmitterTokens.COLON);
					writeToken(ASEmitterTokens.BLOCK_OPEN);
					write("type");
					writeToken(ASEmitterTokens.COLON);
					write(ASEmitterTokens.SINGLE_QUOTE);
					write(var.type);
					write(ASEmitterTokens.SINGLE_QUOTE);
					
					//provide a get_set function that works in release build with public vars
					writeToken(ASEmitterTokens.COMMA);
					write(JSRoyaleEmitterTokens.ROYALE_REFLECTION_INFO_GET_SET);
					writeToken(ASEmitterTokens.COLON);
					writeToken(ASEmitterTokens.FUNCTION);
					boolean valueIsUntyped = var.type.equals("*");
					if (valueIsUntyped) {
						//give the function a local name because a self-reference argument will be used to signify that
						//it is not being used as a setter (because 'undefined' is a valid possible value to set)
						write("f");
					}
					write(ASEmitterTokens.PAREN_OPEN);
					
					if (!var.isStatic) {
						//instance type parameter
						writeToken("/** " + typeName + " */");
						write("inst");
						writeToken(ASEmitterTokens.COMMA);
					}
					//any type for value
					write("/** * */ v");
					writeToken(ASEmitterTokens.PAREN_CLOSE);
					write(ASEmitterTokens.BLOCK_OPEN);
					String getterSetter;
					String varName;
					if (var.customNS != null) {
						varName = JSRoyaleEmitter.formatNamespacedProperty(var.customNS, var.name, false);
					} else varName = var.name;
					
					String field = var.isStatic ? typeName + "." + varName : "inst." + varName;
					if (valueIsUntyped) {
						//to avoid setting when type is '*' set the 'value' param to the function being called, which
						//causes a 'getter only' result
						//In the case of no parameter or literal undefined being passed, it will be treated as the value
						//of undefined to be assigned to the variable field
						getterSetter = "return v !== f ? "+ field + " = v : " + field + ";";
					} else {
						getterSetter = "return v !== undefined ? " + field + " = v : " + field + ";";
					}
					write(getterSetter);
					write(ASEmitterTokens.BLOCK_CLOSE);
					
					IMetaTagNode[] tags = var.metaData;
					if (tags != null) {
						//writeToken(ASEmitterTokens.COMMA);
						writeMetaData(tags, true, false);
					}
					// close object
					write(ASEmitterTokens.BLOCK_CLOSE);
				}
				indentPop();
				writeNewline();
				write(ASEmitterTokens.BLOCK_CLOSE);
				write(ASEmitterTokens.SEMICOLON);
				indentPop();
				writeNewline();
				// close variable function
				write(ASEmitterTokens.BLOCK_CLOSE);
				continueContent = true;
			
			}
		}
	    
	 

		if (accessorData.size() > 0) {
			if (continueContent) {
				write(ASEmitterTokens.COMMA);
				writeNewline();
			}
			// accessors: function() {
			if (!indented) {
				indentPush();
				writeNewline();
				indented = true;
			}
			
			
			write("accessors");
			writeToken(ASEmitterTokens.COLON);
			writeToken(ASEmitterTokens.FUNCTION);
			write(ASEmitterTokens.PAREN_OPEN);
			writeToken(ASEmitterTokens.PAREN_CLOSE);
			write(ASEmitterTokens.BLOCK_OPEN);
			indentPush();
			writeNewline();
			// return {
			writeToken(ASEmitterTokens.RETURN);
			write(ASEmitterTokens.BLOCK_OPEN);
			indentPush();

			count = 0;
			for (AccessorData accessor : accessorData)
			{
				if (count > 0)
					write(ASEmitterTokens.COMMA);
				writeNewline();
				count++;
				// accessorname: { type: typename
				write(ASEmitterTokens.SINGLE_QUOTE);
				//prefix static accessor names with |
				if (accessor.isStatic) {
					write("|");
				}
				if (accessor.customNS != null) {
					write(accessor.customNS);
					write("::");
				}
				write(accessor.name);
				write(ASEmitterTokens.SINGLE_QUOTE);
				writeToken(ASEmitterTokens.COLON);
				writeToken(ASEmitterTokens.BLOCK_OPEN);
				write("type");
				writeToken(ASEmitterTokens.COLON);
				write(ASEmitterTokens.SINGLE_QUOTE);
				write(accessor.type);
				write(ASEmitterTokens.SINGLE_QUOTE);
				writeToken(ASEmitterTokens.COMMA);
				write("access");
				writeToken(ASEmitterTokens.COLON);
				write(ASEmitterTokens.SINGLE_QUOTE);
				write(accessor.access);
				write(ASEmitterTokens.SINGLE_QUOTE);
				writeToken(ASEmitterTokens.COMMA);
				write("declaredBy");
				writeToken(ASEmitterTokens.COLON);
				write(ASEmitterTokens.SINGLE_QUOTE);
				write(accessor.declaredBy);
				write(ASEmitterTokens.SINGLE_QUOTE);
				IMetaTagNode[] tags = accessor.metaData;
				if (tags != null)
				{
					//writeToken(ASEmitterTokens.COMMA);
					writeMetaData(tags, true, false);
				}
				// close object
				write(ASEmitterTokens.BLOCK_CLOSE);
			}
			indentPop();
			writeNewline();
			write(ASEmitterTokens.BLOCK_CLOSE);
			write(ASEmitterTokens.SEMICOLON);
			indentPop();
			writeNewline();
			// close accessor function
			write(ASEmitterTokens.BLOCK_CLOSE);
			continueContent = true;
		}

	 
		if (methodData.size() > 0) {
			if (continueContent){
				write(ASEmitterTokens.COMMA);
				writeNewline();
			}
			
			if (!indented) {
				indentPush();
				writeNewline();
				indented = true;
			}
			
			write("methods");
			writeToken(ASEmitterTokens.COLON);
			writeToken(ASEmitterTokens.FUNCTION);
			write(ASEmitterTokens.PAREN_OPEN);
			writeToken(ASEmitterTokens.PAREN_CLOSE);
			write(ASEmitterTokens.BLOCK_OPEN);
			indentPush();
			writeNewline();
			// return {
			writeToken(ASEmitterTokens.RETURN);
			write(ASEmitterTokens.BLOCK_OPEN);
			indentPush();

			count = 0;
			for (MethodData method : methodData)
			{
				if (count > 0)
					write(ASEmitterTokens.COMMA);
				writeNewline();
				count++;
				// methodname: { type: typename
				write(ASEmitterTokens.SINGLE_QUOTE);
				//prefix static method names with |
				if (method.isStatic) {
					write("|");
				}
				if (method.customNS != null) {
					write(method.customNS);
					write("::");
				}
				write(method.name);
				write(ASEmitterTokens.SINGLE_QUOTE);
				writeToken(ASEmitterTokens.COLON);
				writeToken(ASEmitterTokens.BLOCK_OPEN);
				write("type");
				writeToken(ASEmitterTokens.COLON);
				write(ASEmitterTokens.SINGLE_QUOTE);
				write(method.type);
				write(ASEmitterTokens.SINGLE_QUOTE);
				writeToken(ASEmitterTokens.COMMA);
				write("declaredBy");
				writeToken(ASEmitterTokens.COLON);
				write(ASEmitterTokens.SINGLE_QUOTE);
				write(method.declaredBy);
				write(ASEmitterTokens.SINGLE_QUOTE);

				IParameterNode[] params = method.parameters;
				//only output params if there are any
				if (params!=null && params.length > 0) {
					writeToken(ASEmitterTokens.COMMA);
					writeParameters(params);
				}
				IMetaTagNode[] metas = method.metaData;
				if (metas != null)
				{
					writeMetaData(metas, true, false);
				}

				// close object
				write(ASEmitterTokens.BLOCK_CLOSE);
			}
			// close return
			indentPop();
			writeNewline();
			write(ASEmitterTokens.BLOCK_CLOSE);
			write(ASEmitterTokens.SEMICOLON);
			indentPop();
			writeNewline();
			// close method function
			write(ASEmitterTokens.BLOCK_CLOSE);
			continueContent = true;
		}
		
    	if (metaData != null && metaData.length > 0)
    	{
    	    writeMetaData(metaData, continueContent, continueContent);
    	}
	    if (indented)
	    	indentPop();
		emitReflectionDataEnd(typeName, indented);
    }
    

	private void writeParameters(IParameterNode[] params)
	{
		// parameters: function() {
		write("parameters");
		writeToken(ASEmitterTokens.COLON);
		writeToken(ASEmitterTokens.FUNCTION);
		write(ASEmitterTokens.PAREN_OPEN);
		writeToken(ASEmitterTokens.PAREN_CLOSE);
		writeToken(ASEmitterTokens.BLOCK_OPEN);
		// return [ array of parameter definitions ]
		writeToken(ASEmitterTokens.RETURN);
		writeToken(ASEmitterTokens.SQUARE_OPEN);

		int len = params.length;
		for (int i = 0; i < len ; i++) {
			IParameterDefinition parameterDefinition = (IParameterDefinition) params[i].getDefinition();

			write(ASEmitterTokens.SINGLE_QUOTE);
			ITypeDefinition pd = parameterDefinition.resolveType(getProject());
			if (pd == null)
			{
				UnknownTypeProblem problem = new UnknownTypeProblem(parameterDefinition.getNode(), parameterDefinition.getQualifiedName());
				getProject().getProblems().add(problem);
				write("not found");
			}
			else
				write(pd.getQualifiedName());
			write(ASEmitterTokens.SINGLE_QUOTE);

			write(ASEmitterTokens.COMMA);
			write(ASEmitterTokens.SPACE);
			writeToken(parameterDefinition.hasDefaultValue() ? ASEmitterTokens.TRUE :  ASEmitterTokens.FALSE);
			
			if (i < len-1) write(ASEmitterTokens.COMMA);
		}

		// close array of parameter definitions
		write(ASEmitterTokens.SQUARE_CLOSE);
		writeToken(ASEmitterTokens.SEMICOLON);
		// close function
		write(ASEmitterTokens.BLOCK_CLOSE);
	}
	
	private ArrayList<IMetaTagNode> getAllowedMetadata(IMetaTagNode[] tags) {
		JSGoogConfiguration config = ((RoyaleJSProject)getWalker().getProject()).config;
		Set<String> allowedNames = config.getCompilerKeepAs3Metadata();
		
		ArrayList<IMetaTagNode> filteredTags = new ArrayList<IMetaTagNode>(tags.length);
		for (IMetaTagNode tag : tags)
		{
			if (allowedNames.contains(tag.getTagName())) filteredTags.add(tag);
		}
		return filteredTags;
	}
	
	private void writeAllowedMetadata(ArrayList<IMetaTagNode> filteredTags ) {
		int count = 0;
		int len = filteredTags.size();
		
		// metadata: function() {
		write("metadata");
		writeToken(ASEmitterTokens.COLON);
		writeToken(ASEmitterTokens.FUNCTION);
		write(ASEmitterTokens.PAREN_OPEN);
		writeToken(ASEmitterTokens.PAREN_CLOSE);
		writeToken(ASEmitterTokens.BLOCK_OPEN);
		// return [ array of metadata tags ]
		writeToken(ASEmitterTokens.RETURN);
		writeToken(ASEmitterTokens.SQUARE_OPEN);
		
		for (IMetaTagNode tag : filteredTags)
		{
			count++;
			// { name: <tag name>
			writeToken(ASEmitterTokens.BLOCK_OPEN);
			write("name");
			writeToken(ASEmitterTokens.COLON);
			write(ASEmitterTokens.SINGLE_QUOTE);
			write(tag.getTagName());
			write(ASEmitterTokens.SINGLE_QUOTE);
			IMetaTagAttribute[] args = tag.getAllAttributes();
			if (args.length > 0)
			{
				writeToken(ASEmitterTokens.COMMA);
				
				// args: [
				write("args");
				writeToken(ASEmitterTokens.COLON);
				writeToken(ASEmitterTokens.SQUARE_OPEN);
				
				for (int j = 0; j < args.length; j++)
				{
					if (j > 0)
					{
						writeToken(ASEmitterTokens.COMMA);
					}
					// { key: key, value: value }
					IMetaTagAttribute arg = args[j];
					writeToken(ASEmitterTokens.BLOCK_OPEN);
					write("key");
					writeToken(ASEmitterTokens.COLON);
					write(ASEmitterTokens.SINGLE_QUOTE);
					String key = arg.getKey();
					write(key == null ? "" : key);
					write(ASEmitterTokens.SINGLE_QUOTE);
					writeToken(ASEmitterTokens.COMMA);
					write("value");
					writeToken(ASEmitterTokens.COLON);
					write(ASEmitterTokens.SINGLE_QUOTE);
					write(formatJSStringValue(arg.getValue()));
					write(ASEmitterTokens.SINGLE_QUOTE);
					write(ASEmitterTokens.SPACE);
					write(ASEmitterTokens.BLOCK_CLOSE);
				}
				// close array of args
				write(ASEmitterTokens.SPACE);
				write(ASEmitterTokens.SQUARE_CLOSE);
			}
			// close metadata object
			write(ASEmitterTokens.SPACE);
			write(ASEmitterTokens.BLOCK_CLOSE);
			if (count > 0 && count < len)
			{
				writeToken(ASEmitterTokens.COMMA);
			}
		}
		// close array of metadatas
		write(ASEmitterTokens.SPACE);
		write(ASEmitterTokens.SQUARE_CLOSE);
		writeToken(ASEmitterTokens.SEMICOLON);
		// close function
		write(ASEmitterTokens.BLOCK_CLOSE);
	}
    
    private void writeMetaData(IMetaTagNode[] tags, boolean prefixComma, boolean prefixNewline)
    {
		ArrayList<IMetaTagNode> filteredTags = getAllowedMetadata(tags);
		if (filteredTags.size() == 0) {
			//nothing to write
			return;
		}
		if (prefixNewline) {
			if (prefixComma) {
				write(ASEmitterTokens.COMMA);
			}
			writeNewline();
		} else {
			if (prefixComma) {
				writeToken(ASEmitterTokens.COMMA);
			}
		}
		writeAllowedMetadata(filteredTags);
    }

    private String formatJSStringValue(String value) {
		//todo: check other possible metadata values for any need for js string escaping etc
    	value = value.replace("'","\\'");
    	return value;
	}
	
	public void emitReflectionRegisterInitialStaticFields(String typeName, IClassDefinition classDef) {
		//this is only output if the default initializers are enabled (otherwise runtime reflection results are not reliable)
		//local config check here (instead of call site check) - in case this needs to change in the future:
		JSGoogConfiguration config = ((RoyaleJSProject)getWalker().getProject()).config;
		if (config == null || !config.getJsDefaultInitializers()) return;
		
		boolean needsStaticsList = false;
		Collection<IDefinitionSet> defs = classDef.getContainedScope().getAllLocalDefinitionSets();
		for (IDefinitionSet set : defs) {
			for (int i = 0, l = set.getSize(); i < l; ++i) {
				IDefinition d = set.getDefinition(i);
				if (d.isStatic()) {
					needsStaticsList = true;
					break;
				}
			}
			if (needsStaticsList) break;
		}
		if (needsStaticsList) {
			//support for reflection on static classes: supports ability to distinguish between initial fields and dynamic fields
			//this is excluded via dead-code-elimination if never used
			//doc emitter-ish:
			writeNewline("/**");
			writeNewline(" * Provide reflection support for distinguishing dynamic fields on class object (static)");
			writeNewline(" * @const");
			writeNewline(" * @type {Array<string>}");
			writeNewline(" */");
			
			//{typeName}.prototype.ROYALE_INITIAL_STATICS = Object.keys({typeName});
			write(typeName);
			write(ASEmitterTokens.MEMBER_ACCESS);
			write(JSEmitterTokens.PROTOTYPE);
			write(ASEmitterTokens.MEMBER_ACCESS);
			writeToken(JSRoyaleEmitterTokens.ROYALE_REFLECTION_INFO_INITIAL_STATICS);
			writeToken(ASEmitterTokens.EQUAL);
			write("Object.keys");
			write(ASEmitterTokens.PAREN_OPEN);
			write(typeName);
			write(ASEmitterTokens.PAREN_CLOSE);
			write(ASEmitterTokens.SEMICOLON);
			writeNewline();
		}
	}
    
    public void emitExportProperties(String typeName, ArrayList<String> exportProperties, ArrayList<String> exportSymbols)
    {
    	for (String prop : exportSymbols)
    	{
    		write(JSRoyaleEmitterTokens.GOOG_EXPORT_SYMBOL);
    		write(ASEmitterTokens.PAREN_OPEN);
    		write(ASEmitterTokens.SINGLE_QUOTE);
    		write(typeName);
    		write(ASEmitterTokens.MEMBER_ACCESS);
    		write(prop);
    		write(ASEmitterTokens.SINGLE_QUOTE);
    		write(ASEmitterTokens.COMMA);
    		write(ASEmitterTokens.SPACE);
    		write(typeName);
    		write(ASEmitterTokens.MEMBER_ACCESS);
    		write(prop);
    		write(ASEmitterTokens.PAREN_CLOSE);
    		writeNewline(ASEmitterTokens.SEMICOLON);
    	}
    	for (String prop : exportProperties)
    	{
    		write(JSRoyaleEmitterTokens.GOOG_EXPORT_PROPERTY);
    		write(ASEmitterTokens.PAREN_OPEN);
    		write(typeName);
    		write(ASEmitterTokens.MEMBER_ACCESS);
    		write(JSEmitterTokens.PROTOTYPE);
    		write(ASEmitterTokens.COMMA);
    		write(ASEmitterTokens.SPACE);
    		write(ASEmitterTokens.SINGLE_QUOTE);
    		write(prop);
    		write(ASEmitterTokens.SINGLE_QUOTE);
    		write(ASEmitterTokens.COMMA);
    		write(ASEmitterTokens.SPACE);
    		write(typeName);
    		write(ASEmitterTokens.MEMBER_ACCESS);
    		write(JSEmitterTokens.PROTOTYPE);
    		write(ASEmitterTokens.MEMBER_ACCESS);
    		write(prop);
    		write(ASEmitterTokens.PAREN_CLOSE);
    		writeNewline(ASEmitterTokens.SEMICOLON);
    	}
    }
}
