/*
 *
 *  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.flex.compiler.internal.targets;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import org.apache.flex.abc.ABCConstants;
import org.apache.flex.abc.ABCEmitter;
import org.apache.flex.abc.ABCLinker;
import org.apache.flex.abc.ABCParser;
import org.apache.flex.abc.EntryOrderedStore;
import org.apache.flex.abc.ABCEmitter.EmitterClassVisitor;
import org.apache.flex.abc.Pool;
import org.apache.flex.abc.semantics.Metadata;
import org.apache.flex.abc.semantics.MethodInfo;
import org.apache.flex.abc.semantics.Name;
import org.apache.flex.abc.semantics.Namespace;
import org.apache.flex.abc.semantics.Trait;
import org.apache.flex.compiler.config.RSLSettings;
import org.apache.flex.compiler.constants.IASLanguageConstants;
import org.apache.flex.compiler.constants.IMetaAttributeConstants;
import org.apache.flex.compiler.definitions.IDefinition;
import org.apache.flex.compiler.definitions.references.IResolvedQualifiersReference;
import org.apache.flex.compiler.definitions.references.ReferenceFactory;
import org.apache.flex.compiler.exceptions.BuildCanceledException;
import org.apache.flex.compiler.internal.caches.SWFCache;
import org.apache.flex.compiler.internal.definitions.ClassDefinition;
import org.apache.flex.compiler.internal.projects.CompilerProject;
import org.apache.flex.compiler.internal.projects.FlexProject;
import org.apache.flex.compiler.internal.scopes.ASProjectScope;
import org.apache.flex.compiler.internal.units.SWCCompilationUnit;
import org.apache.flex.compiler.problems.ICompilerProblem;
import org.apache.flex.compiler.problems.UnexpectedExceptionProblem;
import org.apache.flex.compiler.targets.ISWFTarget;
import org.apache.flex.compiler.targets.ITargetProgressMonitor;
import org.apache.flex.compiler.targets.ITargetReport;
import org.apache.flex.compiler.targets.ITargetSettings;
import org.apache.flex.compiler.units.ICompilationUnit;
import org.apache.flex.compiler.units.ICompilationUnit.UnitType;
import org.apache.flex.compiler.units.requests.ISWFTagsRequestResult;
import org.apache.flex.swc.ISWC;
import org.apache.flex.swc.ISWCLibrary;
import org.apache.flex.swf.ISWF;
import org.apache.flex.swf.SWF;
import org.apache.flex.swf.SWFFrame;
import org.apache.flex.swf.ISWFConstants;
import org.apache.flex.swf.tags.DoABCTag;
import org.apache.flex.swf.tags.IManagedTag;
import org.apache.flex.swf.tags.ITag;
import org.apache.flex.swf.tags.ScriptLimitsTag;
import org.apache.flex.swf.tags.SymbolClassTag;
import org.apache.flex.swf.types.RGB;
import org.apache.flex.swf.types.Rect;
import com.google.common.base.Function;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;

/**
 * Concrete implementation of ITarget for building a collection of source files
 * into a SWF.
 */
public abstract class SWFTarget extends Target implements ISWFTarget
{
    protected static final class SWFFrameInfo
    {
        public static final boolean EXTERNS_ALLOWED = true;
        public static final boolean EXTERNS_DISALLOWED = false;
        
        public SWFFrameInfo(String frameLabel, boolean allowExternals, Set<ICompilationUnit> rootedUnits, Iterable<ICompilerProblem> problems)
        {
            // character replaced came from the old compiler, so copy to match behavior
            this.frameLabel = frameLabel != null ? frameLabel.replaceAll( "[^A-Za-z0-9]", "_" ) : null;
            this.allowExternals = allowExternals;
            this.rootedUnits = rootedUnits;
            this.problems = problems;
        }
        
        public SWFFrameInfo(Set<ICompilationUnit> rootedUnits, Iterable<ICompilerProblem> problems)
        {
            this(null, EXTERNS_ALLOWED, rootedUnits, problems);
        }

        public final String frameLabel;
        public final boolean allowExternals;
        public final Set<ICompilationUnit> rootedUnits;
        public final Iterable<ICompilerProblem> problems;
    }

    public SWFTarget(CompilerProject project, ITargetSettings targetSettings, ITargetProgressMonitor progressMonitor)
    {
        super(project, targetSettings, progressMonitor);
    }

    private Collection<ICompilerProblem> problemCollection;
    private Target.RootedCompilationUnits rootedCompilationUnits;
    protected Set<String> metadataDonators = new HashSet<String>();
    protected boolean isLibrary = false;
    	
    /** 
     * Cached list of compilation units. This is a performance optimization to keep us from
     * making redundant calls to topologicalSort.
     * 
     * Note that this optimization only gives a small boost in observed cases.
     * 
     * if non-null, this is the results of calling project.getReachableCompilationUnitsInSWFOrder(rootedCU);
     * We will assume it doesn't change
     */
    
    private List<ICompilationUnit> rootedCompilationUnitsAndDependenciesInSWFOrder;
    
    /**
     * Cached information about all the frames in the SWF.
     */
    private FramesInformation framesInformation;
    
    /**
     * Cached {@link RGB} value for the SWF's background color.
     */
    private RGB swfBackgroundColor;
    
    
    /**
     * Cached {@link ITargetAttributes} for the SWF
     */
    private ITargetAttributes _targetAttributes;
   
    /**
     * Gets the set of {@link ICompilationUnit}s that are the roots of the graph of
     * {@link ICompilationUnit}s whose output will be in the generate SWF.
     * @return The set of {@link ICompilationUnit}s that are the roots of the graph of
     * {@link ICompilationUnit}s whose output will be in the generate SWF
     */
    @Override
    public RootedCompilationUnits getRootedCompilationUnits() throws InterruptedException
    {
        if (rootedCompilationUnits == null)
            rootedCompilationUnits = computeRootedCompilationUnits();
        return rootedCompilationUnits;
    }
    
    /**
     * Same as project.getReachableCompilationUnitsInSWFOrder(), but with a cache for the case of rooted compilation units
     * @throws InterruptedException 
     */
    List<ICompilationUnit> getReachableCompilationUnitsInSWFOrder( Collection<ICompilationUnit> roots ) throws InterruptedException
    {
        List<ICompilationUnit> ret = null;
        
        final RootedCompilationUnits rootedCompilationUnits = getRootedCompilationUnits();
        
        // Determine if the "roots" in this call are the rooted compilation units for this target.
        // We only cached the results for this case
        boolean passedInRootedCompilationUnits = false;
        if (roots.size() == rootedCompilationUnits.getUnits().size())
        {
            passedInRootedCompilationUnits = true;
            for (ICompilationUnit cu : roots)
            {
                if (!rootedCompilationUnits.getUnits().contains(cu))
                    passedInRootedCompilationUnits = false;
            }
        }
        
        // If this is the case that is cached, then get/make the cache
        if (passedInRootedCompilationUnits)
        {
            if (rootedCompilationUnitsAndDependenciesInSWFOrder == null)
            {
                rootedCompilationUnitsAndDependenciesInSWFOrder =  project.getReachableCompilationUnitsInSWFOrder(roots);           
            }
            ret = rootedCompilationUnitsAndDependenciesInSWFOrder;
        }
        else
        {
            // If not the cached case, just call the function directly
            ret = project.getReachableCompilationUnitsInSWFOrder(roots);
        }
        assert ret != null;
        
        return ret;
    }
     
    /**
     * Absolute path of the path that contains the reference to Object.
     * We use this to determine which SWC contains native code so that
     * we always exclude all of the definitions from that SWC.
     */
    private String pathContainingObject;

    @Override
    public ISWF build(Collection<ICompilerProblem> problems)
    {
        buildStarted();
        try
        {
            Iterable<ICompilerProblem> fatalProblems = getFatalProblems();
            if (!Iterables.isEmpty(fatalProblems))
            {
                Iterables.addAll(problems, fatalProblems);
                return null;
            }

            Set<ICompilationUnit> compilationUnitSet = new HashSet<ICompilationUnit>();
            Target.RootedCompilationUnits rootedCompilationUnits = getRootedCompilationUnits();
            
            // no rooted compilation could be found, but still create an empty SWF
            // in this error case
            if (rootedCompilationUnits.getUnits().isEmpty())
                return buildEmptySWF();

            compilationUnitSet.addAll(rootedCompilationUnits.getUnits());

            this.problemCollection = problems;

            FramesInformation frames = getFramesInformation();
            
            BuiltCompilationUnitSet builtCompilationUnits =
                getBuiltCompilationUnitSet();
            Iterables.addAll(problems, builtCompilationUnits.problems);
            
            doPostBuildWork(builtCompilationUnits.compilationUnits, problems);
            
            ISWF swf = initializeSWF(getReachableCompilationUnitsInSWFOrder(rootedCompilationUnits.getUnits()));
            
            // now that everything is built, the dependency graph is populated enough to do a topological sort on
            // all compilation units needed by this target.
            // The compilation units that define bases classes must occurs in the swf before
            // compilation units that define classes that subclass those classes ( see
            // inheritance dependencies in the {@link DependencyGraph} ).
            Set<ICompilationUnit> emittedCompilationUnits = new HashSet<ICompilationUnit>();
            
            frames.createFrames(this, swf, builtCompilationUnits.compilationUnits, emittedCompilationUnits, problems);
            
            createLinkReport(problems);
            
            // "Link" the resulting swf, if the optimize flag is set
            return linkSWF(swf);
        }
        catch (BuildCanceledException bce)
        {
            return null;
        }
        catch (InterruptedException ie)
        {
            return null;
        }
        finally
        {
            buildFinished();
        }
    }

    @Override
    public TargetType getTargetType()
    {
        return TargetType.SWF;
    }
   
    protected final ITargetAttributes getTargetAttributes() throws InterruptedException
    {
        // if already computed, just return the cached value
        if (_targetAttributes == null)
        {
            // first time - delegate to subclass to compute
            _targetAttributes = computeTargetAttributes();
        }
        return _targetAttributes;
    }
    
    /**
     * round-up  user specified target attributes
     * All derived classes must provide one, but they are free to provide "do nothing" implementations
     * (like NilTargetAttributes)
     */
    protected abstract ITargetAttributes computeTargetAttributes() throws InterruptedException;
    
    /**
     * Create the {@link FramesInformation} which contains the skeleton for the frames
     * of this SWF. The actual frames will be create in doCreateFrames().
     * @throws InterruptedException 
     */
    protected abstract FramesInformation computeFramesInformation() throws InterruptedException;
    
    protected final FramesInformation getFramesInformation() throws InterruptedException
    {
        if (framesInformation != null)
            return framesInformation;
        framesInformation = computeFramesInformation();
        return framesInformation;
    }
    
    /**
     * Check the build and analyze the results before the SWF target is
     * initialized.
     * 
     * @param compilationUnits The set of compilation units after
     * buildAndCollectProblems() has run.
     * @param problems A collection where discovered problems are appended.
     */
    protected void doPostBuildWork(ImmutableSet<ICompilationUnit> compilationUnits,
            Collection<ICompilerProblem> problems) throws InterruptedException
    {
        
    }

    /**
     * Creates a new instance of a SWF.
     * 
     * @return a new instance of a SWF.
     */
    protected SWF buildEmptySWF()
    {
        return new SWF();
    }

    /**
     * Add to the collection of compiler problems.
     * 
     * @param problem
     */
    protected void reportProblem(ICompilerProblem problem)
    {
        assert problemCollection != null;
        
        problemCollection.add(problem);
    }

    /**
     * Add a set of root classes and its dependencies to a new frame or to an existing
     * frame.
     * @param frame if null a new frame will be created for the classes. Otherwise the 
     * classes will be added to the existing frame.
     * @param frameRootClasses
     * @param projectScope
     * @param allowExternals
     * @param emittedCompilationUnits
     * @return The SWF frame.
     * @throws InterruptedException
     */
    protected SWFFrame createWithClassesAndItsDependencies(SWFFrame frame, 
            Collection<ClassDefinition> frameRootClasses, ASProjectScope projectScope,
            boolean allowExternals,
            Set<ICompilationUnit> emittedCompilationUnits) throws InterruptedException
    {
        final List<ICompilationUnit> rootedUnitsForFrame = new LinkedList<ICompilationUnit>();
        for (ClassDefinition frameRootClass : frameRootClasses)
        {
            final Collection<IDefinition> extraDefinitions = frameRootClass.resolveExtraClasses(project);
            final ICompilationUnit frameFactoryClassCompilationUnit = projectScope.getCompilationUnitForDefinition(frameRootClass);
            assert frameFactoryClassCompilationUnit != null;
            rootedUnitsForFrame.add(frameFactoryClassCompilationUnit);
            for (IDefinition extraDef : extraDefinitions)
            {
                if (!extraDef.isImplicit())
                {
                    ICompilationUnit extraDefCompilationUnit = projectScope.getCompilationUnitForDefinition(extraDef);
                    assert extraDefCompilationUnit != null;
                    rootedUnitsForFrame.add(extraDefCompilationUnit);
                }
            }
        }

        if (frame == null)
            frame = new SWFFrame();

        if (!addCompilationUnitsAndDependenciesToFrame(frame, rootedUnitsForFrame, allowExternals, emittedCompilationUnits))
            return null;

        return frame;
    }

    protected boolean addCompilationUnitsAndDependenciesToFrame(SWFFrame frame,
            Collection<ICompilationUnit> rootedUnitsForFrame, 
            boolean allowExternals,
            Set<ICompilationUnit> emittedCompilationUnits) throws InterruptedException
    {
        List<ICompilationUnit> unitsForFrame = this.getReachableCompilationUnitsInSWFOrder(rootedUnitsForFrame);
        for (ICompilationUnit cu : unitsForFrame)
        {
            if (emittedCompilationUnits.add(cu))
            {
                boolean includeCu = testCompilationUnitLinkage(cu, allowExternals);
                doAddMetadataNamesToTarget(cu, includeCu);
                
                if (includeCu)
                {
                	ISWFTagsRequestResult swfTags = cu.getSWFTagsRequest().get();
                	if (targetSettings.allowSubclassOverrides() && !isLibrary)
                	{
                		// scan the ABC in each CU for overrides that need fixing.
                		// the override needs to be put back to the base override
                		// otherwise you will get a verify error at runtime
                		boolean changedABC = false;
                        final DoABCTag doABC = swfTags.getDoABCTag();
                        ABCParser parser = new ABCParser(doABC.getABCData());
                        ABCEmitter emitter = new ABCEmitter();
                        try {
                        	parser.parseABC(emitter);
	                        Collection<EmitterClassVisitor> classes = emitter.getDefinedClasses();
	                        for (EmitterClassVisitor clazz : classes)
	                        {
	                        	System.out.println("scanning for overrides: " + clazz.getInstanceInfo().name.getBaseName());
	                        	Iterator<Trait> instanceTraits = clazz.instanceTraits.iterator();
	                        	while (instanceTraits.hasNext())
	                        	{
	                        		Trait trait = instanceTraits.next();
	                        		Vector<Metadata> metas = trait.getMetadata();
	                        		metas:
	                        		for (Metadata meta : metas)
	                        		{
	                        			if (meta.getName().equals(IMetaAttributeConstants.ATTRIBUTE_SWFOVERRIDE))
	                        			{
	                                        EntryOrderedStore<MethodInfo> methods = emitter.getMethodInfos();
	                                        for (MethodInfo method : methods)
	                                        {
	                                        	String methodName = method.getMethodName();
	                                        	if (methodName == null) continue;
	                                        	if (methodName.equals(trait.getName().getBaseName()))
	                                        	{
	                                        		String[] keys = meta.getKeys();
	                                        		int n = keys.length;
	                                        		for (int i = 0; i < n; i++)
	                                        		{
	                                        			if (keys[i].equals(IMetaAttributeConstants.NAME_SWFOVERRIDE_RETURNS))
	                                        			{
	                                        				String returnString = meta.getValues()[i];
	                                        				int c = returnString.lastIndexOf(".");
	                                        				String packageName = "";
	                                        				String baseName = returnString;
	                                        				if (c != -1)
	                                        				{
	                                        					packageName = returnString.substring(0, c);
	                                        					baseName = returnString.substring(c + 1);
	                                        				}
	                                        				
	                                        				Pool<Name> namePool = emitter.getNamePool();
	                                        				List<Name> nameList = namePool.getValues();
	                                        				boolean foundName = false;
	                                        				for (Name name : nameList)
	                                        				{
	                                        					String base = name.getBaseName();
	                                        					if (base == null) continue;
	                                        					if (name.getQualifiers().length() != 1) continue;
	                                        					Namespace ns = name.getSingleQualifier();
	                                        					if (ns == null) continue;
	                                        					String nsName = ns.getName();
	                                        					if (nsName == null) continue;
	                                        					if (base.equals(baseName) &&
	                                        							nsName.equals(packageName))
	                                        					{
	                                                				method.setReturnType(name);
	                                                				foundName = true;
	                                                				changedABC = true;
	                                                				break metas;
	                                        					}
	                                        				}
	                                        				if (!foundName)
	                                        				{
	                                            				Pool<String> stringPool = emitter.getStringPool();
	                                            				stringPool.add(packageName);// theoretically, it won't be added if already there
	                                            				stringPool.add(baseName);	// theoretically, it won't be added if already there
	                                        					Namespace ns = new Namespace(ABCConstants.CONSTANT_PackageNs, packageName);
	                                        					Pool<Namespace> nsPool = emitter.getNamespacePool();
	                                        					nsPool.add(ns);
	                                        					Name name = new Name(ns, baseName);
	                                        					namePool.add(name);
	                                        					method.setReturnType(name);
	                                        					changedABC = true;
	                                            				break metas;
	                                        				}
	                                        			}
	                                        			else if (keys[i].equals(IMetaAttributeConstants.NAME_SWFOVERRIDE_PARAMS))
	                                        			{
	                                        				String paramList = meta.getValues()[i];
	                                    					String[] parts;
	                                    					if (paramList.contains(","))
	                                    						parts = paramList.split(",");
	                                    					else
	                                    					{
	                                    						parts = new String[1];
	                                    						parts[0] = paramList;
	                                    					}
	                                    					Vector<Name> newList = new Vector<Name>();
	                                    					for (String part : parts)
	                                    					{
		                                        				int c = part.lastIndexOf(".");
		                                        				String packageName = "";
		                                        				String baseName = part;
		                                        				if (c != -1)
		                                        				{
		                                        					packageName = part.substring(0, c);
		                                        					baseName = part.substring(c + 1);
		                                        				}
		                                        				
		                                        				Pool<Name> namePool = emitter.getNamePool();
		                                        				List<Name> nameList = namePool.getValues();
		                                        				boolean foundName = false;
		                                        				for (Name name : nameList)
		                                        				{
		                                        					String base = name.getBaseName();
		                                        					if (base == null) continue;
		                                        					if (name.getQualifiers().length() != 1) continue;
		                                        					Namespace ns = name.getSingleQualifier();
		                                        					if (ns == null) continue;
		                                        					String nsName = ns.getName();
		                                        					if (nsName == null) continue;
		                                        					if (base.equals(baseName) &&
		                                        							nsName.equals(packageName))
		                                        					{
		                                        						newList.add(name);
		                                                				foundName = true;
		                                                				changedABC = true;
		                                                				break;
		                                        					}
		                                        				}
		                                        				if (!foundName)
		                                        				{
		                                            				Pool<String> stringPool = emitter.getStringPool();
		                                            				stringPool.add(packageName);// theoretically, it won't be added if already there
		                                            				stringPool.add(baseName);	// theoretically, it won't be added if already there
		                                        					Namespace ns = new Namespace(ABCConstants.CONSTANT_PackageNs, packageName);
		                                        					Pool<Namespace> nsPool = emitter.getNamespacePool();
		                                        					nsPool.add(ns);
		                                        					Name name = new Name(ns, baseName);
		                                        					namePool.add(name);
		                                        					newList.add(name);
		                                        					changedABC = true;
		                                        				}
		                                        			}
	                                    					method.setParamTypes(newList);
	                                    					break metas;
	                                        			}
	                                        		}
	                                        	}
	                                        }
	                        			}
	                        		}
	                        	}
	                        }
                        }
                        catch (Exception ee) {}
                        if (changedABC)
                        {
                        	try {
								doABC.setABCData(emitter.emit());
							} catch (Exception e) {
								reportProblem(new UnexpectedExceptionProblem(e));
								return false;
							}
                        }
                	}
                    boolean tagsAdded = swfTags.addToFrame(frame);
                    if (!tagsAdded)
                        return false;
                }
            }
        }
        return true;
    }

    /**
     * Add metadata names to the target for this compilation unit.
     * 
     * @param cu
     * @param linkedIn true if the compilation unit is linked in, false if
     * external.
     */
    protected void doAddMetadataNamesToTarget(ICompilationUnit cu, boolean linkedIn)
    {
        
        if (shouldAddMetadataNamesToTarget(cu, linkedIn))
        {
            if (metadataDonators.add(cu.getAbsoluteFilename()))
            {
                ISWC swc = project.getWorkspace().getSWCManager().
                        get(new File(cu.getAbsoluteFilename()));
                for (ISWCLibrary library : swc.getLibraries())
                {
                    addASMetadataNames(library.getKeepAS3MetadataSet());
                }
            }
                
        }
    }

    /**
     * Test if any metadata names associated with the compilation unit should be
     * added to the target.
     * 
     * @param cu
     * @param linkedIn true if the compilation unit is linked in, false if
     * external.
     * @return true if the metadata names should be included, false otherwise.
     */
    protected boolean shouldAddMetadataNamesToTarget(ICompilationUnit cu, boolean linkedIn)
    {
        return (cu.getCompilationUnitType() == UnitType.SWC_UNIT && 
                !isLinkageAlwaysExternal(cu));
    }

    /**
     * Test if a compilation unit should be include in this target.
     * 
     * @param cu
     * @param allowExternals
     * @return True if the compilation should be included, false otherwise.
     * @throws InterruptedException
     */
    protected boolean testCompilationUnitLinkage(ICompilationUnit cu, boolean allowExternals) throws InterruptedException
    {
        boolean includeCu = true;
        
        if (!allowExternals)
            includeCu = !isLinkageAlwaysExternal(cu);
        else if (isLinkageExternal(cu, targetSettings))
            includeCu = false;
        
        return includeCu;
    }

    /**
     * Test if this compilation unit should always be externalized. Native code
     * cannot be included in an application. We for test native code by checking
     * for the SWC that contains the definition of Object and externalize all of
     * the classes in that SWC. Compilation units that come from an ANE are also
     * always externalized.
     * 
     * @param cu
     * @return true if the compilation unit should always be externalized, false
     * otherwise.
     */
    private boolean isLinkageAlwaysExternal(ICompilationUnit cu)
    {
        if (cu.getCompilationUnitType() != UnitType.SWC_UNIT)
            return false;
        
        // Find the SWC that contains Object.
        if (pathContainingObject == null)
        {
            IResolvedQualifiersReference objectReference = ReferenceFactory.packageQualifiedReference(
                    project.getWorkspace(), 
                    IASLanguageConstants.Object);
            Set<ICompilationUnit> units = project.getScope().
                    getCompilationUnitsForReferences(Collections.singletonList(objectReference));
            assert units.size() == 1;
            
            pathContainingObject = units.iterator().next().getAbsoluteFilename();
            assert pathContainingObject != null;
        }
        
        // If this compilation unit comes from the same SWC as the SWC that
        // contains Object then we must always extern the class.
        if (pathContainingObject.equals(cu.getAbsoluteFilename()))
            return true;
        
        // Test if the compilation unit is from an ANE file.
        if (cu instanceof SWCCompilationUnit)
            return ((SWCCompilationUnit)cu).isANE();
        
        return false;
    }
    
    protected abstract void addLinkedABCToFrame(SWFFrame targetFrame, Iterable<DoABCTag> inputABCs, ABCLinker.ABCLinkerSettings linkSettings) throws Exception;
    
    protected abstract void setKeepAS3MetadataLinkerSetting(ABCLinker.ABCLinkerSettings linkSettings);
    
    /**
     * Link the swf - this handles merging the DoABC tags inside each frame, and will
     * also handle stripping debug opcodes, optimizing the abcs, and/or stripping metadata
     * @param unLinked  the SWF to process
     * @return          A SWF that is the resulting of merging, optimizing, etc.
     */
    protected ISWF linkSWF(ISWF unLinked)
    {
        SWF result = new SWF();
        if( unLinked.getBackgroundColor() != null )
            result.setBackgroundColor(unLinked.getBackgroundColor());
        result.setEnableDebugger2(unLinked.getEnableDebugger2());
        result.setFrameRate(unLinked.getFrameRate());
        result.setFrameSize(unLinked.getFrameSize());
        result.setMetadata(unLinked.getMetadata());
        ScriptLimitsTag scriptLimits = unLinked.getScriptLimits();
        if (scriptLimits != null)
            result.setScriptLimits(scriptLimits.getMaxRecursionDepth(), scriptLimits.getScriptTimeoutSeconds());
        result.setTopLevelClass(unLinked.getTopLevelClass());
        result.setUseAS3(unLinked.getUseAS3());
        result.setUseDirectBlit(unLinked.getUseDirectBlit());
        result.setUseGPU(unLinked.getUseGPU());
        result.setUseNetwork(unLinked.getUseNetwork());
        result.setVersion(unLinked.getVersion());
        result.setProductInfo(unLinked.getProductInfo());
        
        ITargetSettings settings = getTargetSettings();

        ABCLinker.ABCLinkerSettings linkSettings = new ABCLinker.ABCLinkerSettings();

        linkSettings.setOptimize(settings.isOptimized());
        linkSettings.setEnableInlining(project.isInliningEnabled());
        linkSettings.setStripDebugOpcodes(!settings.isDebugEnabled());
        linkSettings.setStripGotoDefinitionHelp(!settings.isDebugEnabled());
        linkSettings.setStripFileAttributeFromGotoDefinitionHelp(settings.isOptimized());
        linkSettings.setProblemsCollection(this.problemCollection);
        linkSettings.setRemoveDeadCode(settings.getRemoveDeadCode());
        
        Collection<String> metadataNames = getASMetadataNames();
        if (settings.isDebugEnabled() && metadataNames != null)
        {
            Collection<String> names = new ArrayList<String>(metadataNames);
            names.add(IMetaAttributeConstants.ATTRIBUTE_GOTODEFINITIONHELP);
            names.add(IMetaAttributeConstants.ATTRIBUTE_GOTODEFINITION_CTOR_HELP);
            metadataNames = names;
        }
        
        setKeepAS3MetadataLinkerSetting(linkSettings);

        for (int i = 0; i < unLinked.getFrameCount(); ++i)
        {
            SWFFrame unlinkedFrame = unLinked.getFrameAt(i);
            SWFFrame resultFrame = new SWFFrame();

            if( unlinkedFrame.getName() != null )
                resultFrame.setName(unlinkedFrame.getName(), unlinkedFrame.hasNamedAnchor());

            LinkedList<DoABCTag> accumulatedABC = new LinkedList<DoABCTag>();
            for (ITag unlinkedTag : unlinkedFrame)
            {
                if (unlinkedTag instanceof DoABCTag)
                {
                    final DoABCTag abcTag = (DoABCTag)unlinkedTag;
                    accumulatedABC.add(abcTag);                        
                }
                else
                {
                    if (!accumulatedABC.isEmpty())
                    {
                        try
                        {
                            addLinkedABCToFrame(resultFrame, accumulatedABC, linkSettings);
                        }
                        catch (Exception e)
                        {
                            return unLinked;
                        }
                        accumulatedABC.clear();
                    }
                    
                    if (!(unlinkedTag instanceof IManagedTag))
                    {
                        resultFrame.addTag(unlinkedTag);
                    }
                    else if( unlinkedTag instanceof SymbolClassTag )
                    {
                        SymbolClassTag s = (SymbolClassTag)unlinkedTag;
                        for( String symbol_name : s.getSymbolNames() )
                        {
                            resultFrame.defineSymbol(s.getSymbol(symbol_name), symbol_name);
                        }
                    }
                }
            }
            if (!accumulatedABC.isEmpty())
            {
                try
                {
                    addLinkedABCToFrame(resultFrame, accumulatedABC, linkSettings);
                }
                catch (Exception e)
                {
                    return unLinked;
                }
                accumulatedABC.clear();
            }
            result.addFrame(resultFrame);
        }
        
        return result;
    }

    /**
     * {@inheritDoc}
     * <p>
     * For {@link SWFTarget}'s the set of rooted {@link ICompilationUnit}s is computed
     * by enumerating all the frames and collecting all the {@link ICompilationUnit}s assigned
     * to each of the frames.
     */
    @Override
    protected RootedCompilationUnits computeRootedCompilationUnits() throws InterruptedException
    {
        final FramesInformation framesInfo = getFramesInformation();
        final RootedCompilationUnits rootedCompilationUnits =
            new RootedCompilationUnits(ImmutableSet.copyOf(framesInfo.getAllCompilationUnits()), framesInfo.getProblems());
        return rootedCompilationUnits;
    }
    
    /**
     * Initialize SWF model with default header values from the target settings
     * when not overridden by the target attributes.
     * 
     * @return SWF model.
     * @throws InterruptedException 
     */
    protected ISWF initializeSWF(List<ICompilationUnit> reachableCompilationUnits) throws InterruptedException
    {
        int swfVersion = targetSettings.getSWFVersion();

        int swfWidth = targetSettings.getDefaultWidth();
        
        ITargetAttributes targetAttributes = getTargetAttributes();
        Float attrWidth = targetAttributes.getWidth();
        if (attrWidth != null)
            swfWidth = attrWidth.intValue();

        int swfHeight = targetSettings.getDefaultHeight();
        Float attrHeight = targetAttributes.getHeight();
        if (attrHeight != null)
            swfHeight = attrHeight.intValue();

        Rect swfFrameSize = new Rect(ISWFConstants.TWIPS_PER_PIXEL * swfWidth,
                                  ISWFConstants.TWIPS_PER_PIXEL * swfHeight);

        float swfFrameRate = targetSettings.getDefaultFrameRate();
        Float attrFrameRate = targetAttributes.getFrameRate();
        if (attrFrameRate != null)
            swfFrameRate = attrFrameRate.floatValue();

        boolean swfUseDirectBlit = targetSettings.useDirectBlit();
        Boolean attrUseDirectBlit = targetAttributes.getUseDirectBlit();
        if (attrUseDirectBlit != null)
            swfUseDirectBlit = attrUseDirectBlit.booleanValue();

        boolean swfUseGPU = targetSettings.useGPU();
        Boolean attrUseGPU = targetAttributes.getUseGPU();
        if (attrUseGPU != null)
            swfUseGPU = attrUseGPU.booleanValue();

        
        final RGB swfBackgroundColorRGB = getBackgroundColor();

        SWF swf = new SWF();
        swf.setVersion(swfVersion);
        swf.setFrameSize(swfFrameSize);
        swf.setFrameRate(swfFrameRate);
        swf.setUseDirectBlit(swfUseDirectBlit);
        swf.setUseGPU(swfUseGPU);
        swf.setBackgroundColor(swfBackgroundColorRGB);
        swf.setUseAS3(swfVersion >= 9);
        swf.setUseNetwork(targetSettings.useNetwork());
        swf.setMetadata(targetSettings.getSWFMetadata());
        
        // Apply the ScriptLimits tag, but only if limits have been specified
        // either in the targetSettings or targetAttributes
        Integer attrScriptRecursionLimit = targetAttributes.getScriptRecursionLimit();
        Integer attrScriptTimeLimit = targetAttributes.getScriptTimeLimit();
        if (targetSettings.areDefaultScriptLimitsSet() || attrScriptRecursionLimit != null || attrScriptTimeLimit != null)
        {
            int swfMaxRecursionDepth = targetSettings.getDefaultScriptRecursionLimit();
            if (attrScriptRecursionLimit != null)
                swfMaxRecursionDepth = attrScriptRecursionLimit.intValue();

            int swfScriptTimeoutSeconds = targetSettings.getDefaultScriptTimeLimit();
            if (attrScriptTimeLimit != null)
                swfScriptTimeoutSeconds = attrScriptTimeLimit.intValue();

            swf.setScriptLimits(swfMaxRecursionDepth, swfScriptTimeoutSeconds);
        }

        return swf;
    }
    
    protected final RGB getBackgroundColor()  throws InterruptedException
    {
        if (swfBackgroundColor != null)
            return swfBackgroundColor;
        
        int swfBackgroundColorInt = targetSettings.getDefaultBackgroundColor();
        String attrBackgroundColorString = getTargetAttributes().getBackgroundColor();
        if (!Strings.isNullOrEmpty(attrBackgroundColorString))
        {
            if (project instanceof FlexProject)
                swfBackgroundColorInt = ((FlexProject)project).getColorAsInt(attrBackgroundColorString);
            else
                swfBackgroundColorInt = Integer.decode(attrBackgroundColorString).intValue();
        }
        swfBackgroundColor = new RGB(swfBackgroundColorInt);
        return swfBackgroundColor;
    }
    
    @Override
    protected ITargetReport computeTargetReport() throws InterruptedException
    {
        BuiltCompilationUnitSet builtCompilationUnits = getBuiltCompilationUnitSet();
        
        return new TargetReport(project, builtCompilationUnits.compilationUnits, Collections.<RSLSettings>emptyList(), 
                getBackgroundColor(), targetSettings, getTargetAttributes(), getLinkageChecker());
    }
    
    /**
     * Contains information about the skeleton of a SWF that is being built by
     * a {@link SWFTarget} and provides methods to create {@link SWFFrame}s and add them
     * to a {@link ISWF}.
     */
    protected static class FramesInformation
    {
        public FramesInformation(Iterable<SWFFrameInfo> frameInfos)
        {
            this.frameInfos = frameInfos;
        }
        
        /**
         * {@link Iterable} of {@link SWFFrameInfo}s which represents the
         * skeleton of a SWF being built by a {@link SWFTarget}.
         */
        public final Iterable<SWFFrameInfo> frameInfos;
        
        /**
         * @return An {@link Iterable} of {@link ICompilerProblem}s that can be
         * used to iterate all the {@link ICompilerProblem}s found while
         * building the skeleton of a SWF being built by a {@link SWFTarget}.
         */
        final Iterable<ICompilerProblem> getProblems()
        {
            Iterable<Iterable<ICompilerProblem>> problemIterables =
                Iterables.transform(frameInfos, new Function<SWFFrameInfo, Iterable<ICompilerProblem>>() {

                    @Override
                    public Iterable<ICompilerProblem> apply(SWFFrameInfo frame)
                    {
                        return frame.problems;
                    }});
            
            return Iterables.concat(problemIterables);
        }
        
        /**
         * @return An {@link Iterable} of {@link ICompilationUnit}s that are rooted by
         * the skeleton of a SWF buing built by a {@link SWFTarget}.
         */
        final Iterable<ICompilationUnit> getAllCompilationUnits()
        {
            Iterable<Iterable<ICompilationUnit>> compilationUnitIterables =
                Iterables.transform(frameInfos, new Function<SWFFrameInfo, Iterable<ICompilationUnit>>() {

                    @Override
                    public Iterable<ICompilationUnit> apply(SWFFrameInfo frame)
                    {
                        return frame.rootedUnits;
                    }});
            return Iterables.concat(compilationUnitIterables);
        }
        
        /**
         * Creates a {@link SWFFrame} for a {@link SWFFrameInfo}.
         * 
         * @param swfTarget The {@link SWFTarget} that is building the SWF to
         * which the newly created {@link SWFFrame} will be added.
         * @param frameInfo The {@link SWFFrameInfo} that represents the skeleton
         * of the SWF frame to create.
         * @param builtCompilationUnits The {@link ImmutableSet} of
         * {@link ICompilationUnit}s that have been built to create the SWF
         * being built by the specified {@link SWFTarget}. This {@link Set} is
         * used to write an assert.
         * @param emittedCompilationUnits The {@link Set} of
         * {@link ICompilationUnit}s that any {@link ICompilationUnit}s added to
         * this frame should be added to. This {@link Set} is used to ensure
         * that each {@link ICompilationUnit} is only added to a single frame in
         * a SWF.
         * @param problems {@link Collection} of {@link ICompilerProblem}s that
         * any {@link ICompilerProblem}s from any {@link ICompilationUnit} added
         * to the new {@link SWFFrame} should be added to.
         * @return A new {@link SWFFrame}.
         * @throws InterruptedException
         */
        protected final SWFFrame createFrame(SWFTarget swfTarget, SWFFrameInfo frameInfo, ImmutableSet<ICompilationUnit> builtCompilationUnits, Set<ICompilationUnit> emittedCompilationUnits, Collection<ICompilerProblem> problems) throws InterruptedException
        {
            Iterables.addAll(problems, frameInfo.problems);
            
            final SWFFrame swfFrame = new SWFFrame();
            
            if (frameInfo.frameLabel != null)
                swfFrame.setName(frameInfo.frameLabel, true);
            
            assert Sets.difference(frameInfo.rootedUnits, builtCompilationUnits).isEmpty()
                : "All compilation units to emit on this frame should have been built!";
            
            if (!swfTarget.addCompilationUnitsAndDependenciesToFrame(swfFrame, frameInfo.rootedUnits,
                    frameInfo.allowExternals, emittedCompilationUnits))
            {
                return null;                
            }
            return swfFrame;
        }
        
        /**
         * Creates all the {@link SWFFrame}s for the SWF skeleton represented by
         * this {@link FramesInformation} and adds them to the specified
         * {@link ISWF}.
         * <p>
         * This method is overridden by sub-classes of {@link FramesInformation}.
         * 
         * @param swfTarget The {@link SWFTarget} that is building the SWF to
         * which the newly created {@link SWFFrame}s will be added.
         * @param swf The {@link ISWF} to which the new created {@link SWFFrame}
         * s will be added.
         * @param builtCompilationUnits The {@link ImmutableSet} of
         * {@link ICompilationUnit}s that have been built to create the SWF
         * being built by the specified {@link SWFTarget}. Sub-classes use this
         * set to generate code that supports startup of the Flex framework.
         * @param emittedCompilationUnits The {@link Set} of
         * {@link ICompilationUnit}s that any {@link ICompilationUnit}s added to
         * this frame should be added to. This {@link Set} is used to ensure
         * that each {@link ICompilationUnit} is only added to a single frame in
         * a SWF.
         * @param problems {@link Collection} of {@link ICompilerProblem}s that
         * any {@link ICompilerProblem}s from any {@link ICompilationUnit} added
         * to the new {@link SWFFrame}s should be added to.
         * @throws InterruptedException
         */
        protected void createFrames(SWFTarget swfTarget, ISWF swf, ImmutableSet<ICompilationUnit> builtCompilationUnits, Set<ICompilationUnit> emittedCompilationUnits, Collection<ICompilerProblem> problems) throws InterruptedException
        {
            for (final SWFFrameInfo frameInfo : frameInfos)
            {
                SWFFrame swfFrame = createFrame(swfTarget, frameInfo, builtCompilationUnits, emittedCompilationUnits, problems);
                swf.addFrame(swfFrame);
            }
        }
    }
    
}
