/*
 *
 *  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 flex2.compiler.mxml;

import flex2.compiler.*;
import flex2.compiler.as3.As3Compiler;
import flex2.compiler.as3.As3Configuration;
import flex2.compiler.as3.BytecodeEmitter;
import flex2.compiler.as3.EmbedExtension;
import flex2.compiler.as3.HostComponentExtension;
import flex2.compiler.as3.SignatureExtension;
import flex2.compiler.as3.StyleExtension;
import flex2.compiler.as3.binding.BindableExtension;
import flex2.compiler.as3.binding.DataBindingExtension;
import flex2.compiler.as3.managed.ManagedExtensionError;
import flex2.compiler.as3.SkinPartExtension;
import flex2.compiler.common.CompilerConfiguration;
import flex2.compiler.io.FileUtil;
import flex2.compiler.io.TextFile;
import flex2.compiler.io.VirtualFile;
import flex2.compiler.mxml.builder.DocumentBuilder;
import flex2.compiler.mxml.dom.AnalyzerAdapter;
import flex2.compiler.mxml.dom.DocumentNode;
import flex2.compiler.mxml.dom.Node;
import flex2.compiler.mxml.gen.VelocityUtil;
import flex2.compiler.mxml.lang.StandardDefs;
import flex2.compiler.mxml.reflect.TypeTable;
import flex2.compiler.mxml.rep.DocumentInfo;
import flex2.compiler.mxml.rep.MxmlDocument;
import flex2.compiler.util.*;
import macromedia.asc.util.ContextStatics;
import org.apache.flex.forks.velocity.Template;
import org.apache.flex.forks.velocity.VelocityContext;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * This class handles the second pass of the mxml subcompiler.  It
 * generates a full implementation and generates byte code.
 * 
 * Changed to extend AbstractSubCompiler to clean up benchmarking code and enable 
 * embedded compiler benchmarking - bfrazer
 */
class ImplementationCompiler extends flex2.compiler.AbstractSubCompiler
{
	private static final String DOC_KEY = "doc";
	private static final String COMMENTS_KEY = "processcomment";
	private static final String CLASSDEF_TEMPLATE_PATH = "flex2/compiler/mxml/gen/";

	private static final String EMPTY_STRING = "";
	private boolean processComments = false;
	
	public ImplementationCompiler(MxmlConfiguration mxmlConfiguration,
	                              As3Configuration ascConfiguration,
	                              NameMappings mappings, Transcoder[] transcoders, boolean processComments )
	{
		this.mxmlConfiguration = mxmlConfiguration;
        this.ascConfiguration = ascConfiguration;
		this.nameMappings = mappings;
        this.processComments = processComments;
        
		mimeTypes = new String[]{MimeMappings.MXML};
		generateDocComments = ascConfiguration.doc();

		// set up ASC and extensions -- mostly mirrors flex2.tools.WebTierAPI.getCompilers()
		asc = new As3Compiler(ascConfiguration);
        
        // signature generation should occur before other extensions can touch the syntax tree.
        if ((ascConfiguration instanceof CompilerConfiguration)
                // currently, both configs reference same object, and are CompilerConfigurations
                && !((CompilerConfiguration)ascConfiguration).getDisableIncrementalOptimizations())
        {
            // SignatureExtension was already initialized in flex2.tools.WebTierAPI.getCompilers()
            asc.addCompilerExtension(SignatureExtension.getInstance());
        }
        String gendir = (mxmlConfiguration.keepGeneratedActionScript()? mxmlConfiguration.getGeneratedDirectory() : null);
		asc.addCompilerExtension(new EmbedExtension(transcoders, gendir, mxmlConfiguration.showDeprecationWarnings()));
		asc.addCompilerExtension(new StyleExtension());
		
		// IMPORTANT!!!! The HostComponentExtension must run before the BindableExtension!!!!
		asc.addCompilerExtension(new HostComponentExtension(mxmlConfiguration.reportMissingRequiredSkinPartsAsWarnings()));
		asc.addCompilerExtension(new SkinPartExtension());
		
		// add binding extension only when processComments is false.
		if(!processComments) 
		{
		    asc.addCompilerExtension(new BindableExtension(gendir, mxmlConfiguration.getGenerateAbstractSyntaxTree(), false));
		} 
		
		asc.addCompilerExtension(new DataBindingExtension(gendir, mxmlConfiguration.showBindingWarnings(),
														  mxmlConfiguration.getGenerateAbstractSyntaxTree(),
                                                          ascConfiguration.getDefine()));
		asc.addCompilerExtension(new ManagedExtensionError());
        // asc.addCompilerExtension(new flex2.compiler.util.TraceExtension());
    }

	private As3Configuration ascConfiguration;
	private MxmlConfiguration mxmlConfiguration;
	private boolean generateDocComments;
	private NameMappings nameMappings;
	private String[] mimeTypes;
	private As3Compiler asc;

	As3Compiler getASCompiler()
	{
		return asc;
	}
	
	public boolean isSupported(String mimeType)
	{
        for (int i = 0; i < mimeTypes.length; i++)
        {
            if (mimeTypes[i].equals(mimeType))
                return true;
        }
        return false;
	}

	public String[] getSupportedMimeTypes()
	{
		return mimeTypes;
	}

	public Source preprocess(Source source)
	{
		return source;
	}

	/**
	 * Traverse the MXML DOM, building an MxmlDocument object. Then use that object to generate AS3 source code.
	 * Then parse that source. 
	 * <p>Note that we're guaranteed to have all the types we need to walk the DOM, due to InterfaceCompiler's
	 * previous traversal which registered the necessary types as dependencies. However, it's still our responsibility
	 * to e.g. generate imports for Classes that are used in the generated program, and so on.
	 */
	public CompilationUnit parse1(Source source, SymbolTable symbolTable)
	{
        CompilationUnit unit = source.getCompilationUnit();

	    // use TypeTable to do the encapsulation - SymbolTable can be too low-level for MXML...
		TypeTable typeTable = (TypeTable) symbolTable.getContext().getAttribute(MxmlCompiler.TYPE_TABLE);
		if (typeTable == null)
		{
			typeTable = new TypeTable(symbolTable, nameMappings, unit.getStandardDefs(),
                                      mxmlConfiguration.getThemeNames());
			symbolTable.getContext().setAttribute(MxmlCompiler.TYPE_TABLE, typeTable);
		}

		/**
		 * Note: because of the way the Compiler framework works, if it's ever the case that <strong>every type request
		 * made by a given iteration of InterfaceCompiler.postprocess() fails to resolve, then postprocess() will not
		 * be reinvoked.<strong> Hence the following.
		 */
		if (hasUnresolvedNodes(unit))
		{
			return null;
		}

		DocumentNode app = (DocumentNode)unit.getSyntaxTree();
		assert app != null;

		DocumentInfo info = (DocumentInfo)unit.getContext().removeAttribute(MxmlCompiler.DOCUMENT_INFO);
		assert info != null;

		//	build MxmlDocument from MXML DOM
		MxmlDocument document = new MxmlDocument(unit, typeTable, info, mxmlConfiguration);
        DocumentBuilder builder = new DocumentBuilder(unit, typeTable, mxmlConfiguration, document);
		app.analyze(builder);

        if (ThreadLocalToolkit.errorCount() > 0)
        {
            return null;
        }

		Source genSource;
		CompilationUnit ascUnit;
		Logger original = ThreadLocalToolkit.getLogger();

		if (mxmlConfiguration.getGenerateAbstractSyntaxTree())
		{
			Logger adapter = new AbstractSyntaxTreeLogAdapter(original);
			ThreadLocalToolkit.setLogger(adapter);

			genSource = generateImplementationAST(document, 
												  symbolTable.perCompileData,
												  symbolTable.emitter);

			// C: null out MxmlDocument after generation
			document.getStylesContainer().setMxmlDocument(null);
			document = null;
			// C: MXML DOM no longer needed
			unit.setSyntaxTree(null);
			
			ascUnit = asc.parse1(genSource, symbolTable);

			if (ThreadLocalToolkit.errorCount() > 0)
			{
				return null;
			}
		}
		else
		{
			// generate AS3 code
			VirtualFile genFile = generateImplementation(document);
			// obtain the line number map...
			DualModeLineNumberMap lineMap = document.getLineNumberMap();

			if (genFile != null && ThreadLocalToolkit.errorCount() == 0)
			{
				genSource = new Source(genFile, source);
				// C: I don't think this is necessary...
				genSource.addFileIncludes(source);
			}
			else
			{
				return null;
			}

			// use MxmlLogAdapter to do filtering, e.g. -generated.as -> .mxml, as line -> mxml line, etc...
			Logger adapter = new MxmlLogAdapter(original, lineMap);
			ThreadLocalToolkit.setLogger(adapter);

			// C: null out MxmlDocument after generation
			document.getStylesContainer().setMxmlDocument(null);
			document = null;
			// C: MXML DOM no longer needed
			unit.setSyntaxTree(null);
			
			// 6. invoke asc
			ascUnit = asc.parse1(genSource, symbolTable);

			if (ThreadLocalToolkit.errorCount() > 0)
			{
				ThreadLocalToolkit.setLogger(original);
				return null;
			}
			
			unit.getContext().setAttribute(MxmlCompiler.LINE_NUMBER_MAP, lineMap);
			// set this so asc can use the line number map to re-map line numbers for debug-mode movies.
			ascUnit.getContext().setAttribute(MxmlCompiler.LINE_NUMBER_MAP, lineMap);
		}

		ThreadLocalToolkit.setLogger(original);

		unit.getContext().setAttribute(MxmlCompiler.DELEGATE_UNIT, ascUnit);

		List bindingExpressions = (List) unit.getContext().getAttribute(CompilerContext.BINDING_EXPRESSIONS);
		ascUnit.getContext().setAttribute(CompilerContext.BINDING_EXPRESSIONS, bindingExpressions);

		unit.getSource().addFileIncludes(ascUnit.getSource());

		Source.transferMetaData(ascUnit, unit);
		Source.transferGeneratedSources(ascUnit, unit);
		Source.transferDefinitions(ascUnit, unit);
		Source.transferInheritance(ascUnit, unit);
		Source.transferExpressions(ascUnit, unit);

		// 7. return CompilationUnit
		return unit;
	}

	public void parse2(CompilationUnit unit, SymbolTable symbolTable)
	{
		CompilationUnit ascUnit = (CompilationUnit) unit.getContext().getAttribute(MxmlCompiler.DELEGATE_UNIT);
		Source.transferInheritance(unit, ascUnit);

		Logger original = setLogAdapter(unit);
		asc.parse2(ascUnit, symbolTable);
		ThreadLocalToolkit.setLogger(original);

		Source.transferAssets(ascUnit, unit);
		Source.transferGeneratedSources(ascUnit, unit);
	}

	public void analyze1(CompilationUnit unit, SymbolTable symbolTable)
	{
		CompilationUnit ascUnit = (CompilationUnit) unit.getContext().getAttribute(MxmlCompiler.DELEGATE_UNIT);

		Logger original = setLogAdapter(unit);
		asc.analyze1(ascUnit, symbolTable);
		ThreadLocalToolkit.setLogger(original);

		Source.transferTypeInfo(ascUnit, unit);
		Source.transferNamespaces(ascUnit, unit);
	}

	public void analyze2(CompilationUnit unit, SymbolTable symbolTable)
	{
		CompilationUnit ascUnit = (CompilationUnit) unit.getContext().getAttribute(MxmlCompiler.DELEGATE_UNIT);
		Source.transferDependencies(unit, ascUnit);

		Logger original = setLogAdapter(unit);
		asc.analyze2(ascUnit, symbolTable);
		ThreadLocalToolkit.setLogger(original);

		Source.transferDependencies(ascUnit, unit);
	}

	public void analyze3(CompilationUnit unit, SymbolTable symbolTable)
	{
		CompilationUnit ascUnit = (CompilationUnit) unit.getContext().getAttribute(MxmlCompiler.DELEGATE_UNIT);
		Source.transferDependencies(unit, ascUnit);

		Logger original = setLogAdapter(unit);
		asc.analyze3(ascUnit, symbolTable);
		ThreadLocalToolkit.setLogger(original);
	}

	public void analyze4(CompilationUnit unit, SymbolTable symbolTable)
	{
		CompilationUnit ascUnit = (CompilationUnit) unit.getContext().getAttribute(MxmlCompiler.DELEGATE_UNIT);
		Logger original = ThreadLocalToolkit.getLogger();

		if (mxmlConfiguration.getGenerateAbstractSyntaxTree())
		{
			Logger adapter = new AbstractSyntaxTreeLogAdapter(original);
			ThreadLocalToolkit.setLogger(adapter);
		}
		else
		{
			LineNumberMap map = (LineNumberMap) unit.getContext().getAttribute(MxmlCompiler.LINE_NUMBER_MAP);
			MxmlLogAdapter adapter = new MxmlLogAdapter(original, map);
			adapter.setRenamedVariableMap( (Map) ascUnit.getContext().getAttribute(CompilerContext.RENAMED_VARIABLE_MAP) );
			ThreadLocalToolkit.setLogger(adapter);
		}

		asc.analyze4(ascUnit, symbolTable);

		if (ThreadLocalToolkit.errorCount() > 0)
		{
			ThreadLocalToolkit.setLogger(original);
			return;
		}

		ThreadLocalToolkit.setLogger(original);

		Source.transferExpressions(ascUnit, unit);
		Source.transferMetaData(ascUnit, unit);
		Source.transferLoaderClassBase(ascUnit, unit);
		Source.transferClassTable(ascUnit, unit);
		Source.transferStyles(ascUnit, unit);
	}

	public void generate(CompilationUnit unit, SymbolTable symbolTable)
	{
		CompilationUnit ascUnit = (CompilationUnit) unit.getContext().getAttribute(MxmlCompiler.DELEGATE_UNIT);

		Logger original = ThreadLocalToolkit.getLogger();

		if (mxmlConfiguration.getGenerateAbstractSyntaxTree())
		{
			Logger adapter = new AbstractSyntaxTreeLogAdapter(original);
			ThreadLocalToolkit.setLogger(adapter);
		}
		else
		{
			LineNumberMap lineNumberMap = (LineNumberMap) unit.getContext().getAttribute(MxmlCompiler.LINE_NUMBER_MAP);

			if (lineNumberMap instanceof DualModeLineNumberMap)
			{
				((DualModeLineNumberMap) lineNumberMap).flushTemp();	//  flush all compile-error-only line number mappings
			}

			Logger adapter = new MxmlLogAdapter(original, lineNumberMap);
			ThreadLocalToolkit.setLogger(adapter);
		}

		asc.generate(ascUnit, symbolTable);

		if (ThreadLocalToolkit.errorCount() > 0)
		{
			ThreadLocalToolkit.setLogger(original);
			return;
		}

		ThreadLocalToolkit.setLogger(original);

		Source.transferGeneratedSources(ascUnit, unit);
		Source.transferBytecodes(ascUnit, unit);
	}

	public void postprocess(CompilationUnit unit, SymbolTable symbolTable)
	{
        // This method is never called, because generate() always produces bytecode, which
        // causes CompilerAPI.postprocess() to skip calling the flex2.compiler.mxml.MxmlCompiler
        // postprocess() method.
	}

	/**
	 *
	 */
	private boolean hasUnresolvedNodes(CompilationUnit unit)
	{
		Set checkNodes = (Set)unit.getContext().removeAttribute(MxmlCompiler.CHECK_NODES);
		if (checkNodes != null && !checkNodes.isEmpty())
		{
			for (Iterator iter = checkNodes.iterator(); iter.hasNext(); )
			{
				Node node = (Node)iter.next();
				ThreadLocalToolkit.log(new AnalyzerAdapter.CouldNotResolveToComponent(node.image), unit.getSource());
			}
		}
        return ThreadLocalToolkit.errorCount() > 0;
	}

	/**
	 *
	 */
	private final VirtualFile generateImplementation(MxmlDocument doc)
	{
	    StandardDefs standardDefs = doc.getStandardDefs();
	    String classDefTemplate = CLASSDEF_TEMPLATE_PATH + standardDefs.getClassDefTemplate();
	    String classDefLibTemplate = CLASSDEF_TEMPLATE_PATH + standardDefs.getClassDefLibTemplate();

		//	load template
		Template template = VelocityManager.getTemplate(classDefTemplate, classDefLibTemplate);
		if (template == null)
		{
			ThreadLocalToolkit.log(new UnableToLoadTemplate(classDefTemplate));
			return null;
		}

		//	evaluate template against document
		String genFileName = MxmlCompiler.getGeneratedName(mxmlConfiguration, doc.getPackageName(), doc.getClassName(),
		                                                        "-generated.as");

		Source source = doc.getCompilationUnit().getSource();

		// C: I would like to guesstimate this number based on MXML component size...
		SourceCodeBuffer out = new SourceCodeBuffer((int) (source.size() * 4));
		try
		{
            DualModeLineNumberMap lineMap = new DualModeLineNumberMap(source.getNameForReporting(), genFileName);
            doc.setLineNumberMap(lineMap);

            VelocityUtil util = new VelocityUtil(CLASSDEF_TEMPLATE_PATH, mxmlConfiguration.debug(), out, lineMap);
			VelocityContext vc = VelocityManager.getCodeGenContext(util);
			vc.put(DOC_KEY, doc);
			// pass whether to care for comments or not 
			vc.put(COMMENTS_KEY, processComments);
		
            template.merge(vc, out);
		}
		catch (Exception e)
		{
			ThreadLocalToolkit.log(new CodeGenerationException(doc.getSourcePath(), e.getLocalizedMessage()));
			return null;
		}

		//	(flush and) return result
		if (out.getBuffer() != null)
		{
			String code = out.toString();

			if (mxmlConfiguration.keepGeneratedActionScript())
			{
				try
				{
					FileUtil.writeFile(genFileName, code);
				}
				catch (IOException e)
				{
					ThreadLocalToolkit.log(new VelocityException.UnableToWriteGeneratedFile(genFileName, e.getLocalizedMessage()));
				}
			}

			// -generated.as should use the originating source timestamp
			return new TextFile(code, genFileName, doc.getCompilationUnit().getSource().getParent(),
			                    MimeMappings.AS, doc.getCompilationUnit().getSource().getLastModified());
		}
		else
		{
			return null;
		}
	}

	private Source generateImplementationAST(MxmlDocument mxmlDocument, ContextStatics contextStatics,
											 BytecodeEmitter bytecodeEmitter)
	{
		String genFileName = MxmlCompiler.getGeneratedName(mxmlConfiguration, mxmlDocument.getPackageName(),
                                                           mxmlDocument.getClassName(), "-generated.as");
		Source source = mxmlDocument.getCompilationUnit().getSource();
		VirtualFile emptyFile = new TextFile(EMPTY_STRING, genFileName, source.getParent(), MimeMappings.AS,
											 System.currentTimeMillis());
		Source result = new Source(emptyFile, source);

		ImplementationGenerator implementationGenerator =
			new ImplementationGenerator(mxmlDocument, generateDocComments, contextStatics,
										result, bytecodeEmitter, ascConfiguration.getDefine(), processComments);

		CompilerContext context = new CompilerContext();
		context.setAscContext(implementationGenerator.getContext());

		Object syntaxTree = implementationGenerator.getSyntaxTree();
		result.newCompilationUnit(syntaxTree, context).setSyntaxTree(syntaxTree);

		return result;
	}

    // error messages

	public static class UnableToLoadTemplate extends CompilerMessage.CompilerError
	{
		private static final long serialVersionUID = 4986512756206073031L;

        public UnableToLoadTemplate(String template)
		{
			this.template = template;
			noPath();
		}

		public String template;
	}

	public static class CodeGenerationException extends CompilerMessage.CompilerError
	{
		private static final long serialVersionUID = -5873407973653883428L;

        public CodeGenerationException(String template, String message)
		{
			super();
			this.template = template;
			this.message = message;
		}

		public final String template, message;
	}

	
    // not needed (we don't expect to ever be a "top level compiler"
    public String getName()
    {
    	assert(false);
        return null;
    }
    
    /**
     * pass down a benchmarker to we can account for time in asc compiler
     * 
     */
    public void setHelper(CompilerBenchmarkHelper helper, boolean isEmb)
    {
    	assert(isEmb);	// we expect that people will pass down the embedded to us, since we are
    					// going to turn around and use is as the MAIN benchmarker for asc.
    	
    	asc.setHelper(helper, false); // Here is the "tricky" bit: we are being passed the embedded helper, 
    			// from above, but we turn anround and pass it to our bemcedded compiler as the "main" helper.
    			// This 
    }

	private Logger setLogAdapter(CompilationUnit unit)
	{
		Logger original = ThreadLocalToolkit.getLogger();

		if (mxmlConfiguration.getGenerateAbstractSyntaxTree())
		{
			Logger adapter = new AbstractSyntaxTreeLogAdapter(original);
			ThreadLocalToolkit.setLogger(adapter);
		}
		else
		{
			LineNumberMap map = (LineNumberMap) unit.getContext().getAttribute(MxmlCompiler.LINE_NUMBER_MAP);
			Logger adapter = new MxmlLogAdapter(original, map);
			ThreadLocalToolkit.setLogger(adapter);
		}

		return original;
	}
}
