/*
 *
 *  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.linker;

import flex2.compiler.CompilationUnit;
import flex2.compiler.Source;
import flex2.compiler.common.FramesConfiguration;
import flex2.compiler.common.FramesConfiguration.FrameInfo;
import flex2.compiler.swc.SwcLibrary;
import flex2.compiler.swc.SwcScript;
import flex2.compiler.util.*;
import flex2.compiler.util.graph.Visitor;
import flash.swf.Frame;
import flash.swf.tags.FrameLabel;

import java.util.*;

/**
 * Extends SimpleMovie by adding support for multiple frames and
 * keeping AS3 metadata.
 */
public class FlexMovie extends SimpleMovie
{
    private List<FrameInfo> frameInfoList;
    private List<FrameInfo> configFrameInfoList;
    private String mainDef;
    private Set<String> externs;
	private Set<String> includes;
    private Set<String> unresolved;
	private SortedSet<String> resourceBundles;
    
    /**
     * List of metadata names that are the unions of the library's metadata names
     * that have script linked into this movie (both internal and external references).
     */
	private Set<String> metadata;
    
    public FlexMovie( LinkerConfiguration linkerConfiguration )
    {
        super( linkerConfiguration );
        mainDef = linkerConfiguration.getMainDefinition();        

        // C: FlexMovie should keep its own copy of externs, includes, unresolved and resourceBundles
        //    so that incremental compilation can do the single-compile-multiple-link scenario.
        externs = new HashSet<String>(linkerConfiguration.getExterns());
	    includes = new LinkedHashSet<String>(linkerConfiguration.getIncludes());
        unresolved = new HashSet<String>(linkerConfiguration.getUnresolved());
        generateLinkReport = linkerConfiguration.generateLinkReport();
        generateRBList = linkerConfiguration.generateRBList();
	    resourceBundles = new TreeSet<String>(linkerConfiguration.getResourceBundles());

        frameInfoList = new LinkedList<FrameInfo>();
        configFrameInfoList = new LinkedList<FrameInfo>();
        configFrameInfoList.addAll( linkerConfiguration.getFrameList() );
        metadata = new HashSet<String>();
    }

    private void prelink( List<CompilationUnit> units ) throws LinkerException
    {
        // Starting at the main definition, build the list of frames and frame classes.
        // No new classes can be discovered here, we're just building the frame class list.

        Map<String, CompilationUnit> def2unit = new HashMap<String, CompilationUnit>();
        for (Iterator<CompilationUnit> it = units.iterator(); it.hasNext(); )
        {
            CompilationUnit unit = it.next();
            mapAll( def2unit, unit.topLevelDefinitions.getStringSet(), unit );
        }

        buildFrames( def2unit, mainDef, new HashSet<String>() );

        frameInfoList.addAll( configFrameInfoList );

        if (frameInfoList.size() > 0)
        {
            topLevelClass = formatSymbolClassName( frameInfoList.get( 0 ).frameClasses.get( 0 ) );
        }
    }

    private boolean hasFrameClass( String queryClassName )
    {
        // This is horribly inefficient, but the inner loop will only get called a few times
        // for a typical Flex movie.
        for (Iterator<FrameInfo> fit = frameInfoList.iterator(); fit.hasNext();)
        {
            FramesConfiguration.FrameInfo frameInfo = fit.next();

            for (Iterator<String> cit = frameInfo.frameClasses.iterator(); cit.hasNext(); )
            {
                String className = cit.next();
                if (className.equals( queryClassName ))
                    return true;
            }
        }
        return false;
    }

    private void buildFrames( Map<String, CompilationUnit> def2unit, String className, Set<String> progress ) throws LinkerException
    {
        if (hasFrameClass( className ))
            return;

        if (progress.contains( className ))
            return;

        progress.add( className );

        CompilationUnit unit = def2unit.get( className );

        if (unit == null)   // this should get picked up elsewhere
            throw new LinkerException.UndefinedSymbolException( className ); // fixme - add special frame class error?

        if (unit.loaderClass != null)
        {
            buildFrames( def2unit, unit.loaderClass, progress );
        }
        FramesConfiguration.FrameInfo info = new FramesConfiguration.FrameInfo();
        info.label = className.replaceAll( "[^A-Za-z0-9]", "_" );
        info.frameClasses.add( className );
	    info.frameClasses.addAll( unit.resourceBundles );
        info.frameClasses.addAll( unit.extraClasses );
        frameInfoList.add( info );
    }

    // shouldn't need swcContext at this point - units should have all referenced defs by now.
    public void generate(List<CompilationUnit> units) throws LinkerException
    {
        try
        {
            prelink( units );
        }
        catch (LinkerException e)
        {
            // You can't actually throw a LinkerException from generate,
            // because an assert fires downstream that expects errorcount > 0!
            // So, we have to warn here and then rethrow.

            ThreadLocalToolkit.log( e );
            throw e;
        }

        List<CULinkable> linkables = new LinkedList<CULinkable>();

		//	TODO remove - see note below
        String serverConfigDef = null;

        CULinkable mainLinkable = null;
        for (Iterator<CompilationUnit> it = units.iterator(); it.hasNext();)
        {
            CompilationUnit unit = it.next();

			//	NOTE Here we watch for specific generated loose code units we have carnal knowledge of, and add their
			//	definitions as deps to the main unit.
			// 	TODO Remove once serverconfigdata is handled within the standard bootstrap setup.
			//
            Source source = unit.getSource();
			String sourceName = source.getName();

            if (sourceName.equals("serverConfigData.as"))
            {
                serverConfigDef = unit.topLevelDefinitions.first().toString();
            }
            CULinkable linkable = new CULinkable( unit );
            if (unit.isRoot())
                mainLinkable = linkable;

            if (source.isInternal())
            {
                externs.addAll( unit.topLevelDefinitions.getStringSet() ); 
            }

            linkables.add( linkable );            
        }

        frames = new ArrayList<Frame>();

        // FIXME - hook serverconfigdata to FlexInit mixin
		if (mainLinkable != null)
		{
            if (serverConfigDef != null)
                mainLinkable.addDep(serverConfigDef);
		}

        try
        {
            final Set<SwcLibrary> librariesProcessed = new HashSet<SwcLibrary>();
            int counter = 0;
            DependencyWalker.LinkState state = new DependencyWalker.LinkState( linkables, externs, includes, unresolved );
            for (Iterator<FrameInfo> it = frameInfoList.iterator(); it.hasNext();)
            {
                FramesConfiguration.FrameInfo frameInfo = it.next();
                final Frame f = new Frame();
	            f.pos = ++counter;

                if (frameInfo.label != null)
                {
                    f.label = new FrameLabel();
                    f.label.label = frameInfo.label;
                }

                // note that we only allow externs on the last frame
                DependencyWalker.traverse( frameInfo.frameClasses, state, !it.hasNext(), !it.hasNext(),
                                           getInheritanceDependenciesOnly(), 
                                           new Visitor<Linkable>()
                {
                    public void visit( Linkable o )
                    {
                        // FIXME - keep an eye on those lazy abcs... do we have loose script?
						//	TODO yep! delete "false &&" once loose-script bootstrapping code has been eliminated - see note above
                        CULinkable l = (CULinkable) o;
                        // exportUnitOnFrame( l.getUnit(), f, false);// && !l.hasDefinition( frameClass ) );
	                    exportUnitOnFrame( l.getUnit(), f, lazyInit);
                        
                        // for any scripts that we include from libraries, add the libraries keep-as3-metadata
                        // to the list of metadata we will preserve in postlink.
                        Source source = l.getUnit().getSource();
                        if (source.isSwcScriptOwner() && !source.isInternal())
                        {
                            SwcScript script = (SwcScript)source.getOwner();
                            SwcLibrary library = script.getLibrary();
                 
                            // lots of scripts, but not many swcs, so avoid adding the same metadata
                            // over and over.
                            if (!librariesProcessed.contains(library))
                            {
                                librariesProcessed.add(library);
                                metadata.addAll(library.getMetadata());
                            }
                        }
                    }
                });
                frames.add( f );
            }

            if (generateLinkReport)
            {
            	linkReport = DependencyWalker.dump( state );
            }
            if (generateRBList)
            {
            	rbList = dumpRBList(resourceBundles);
            }
            
	        if (unresolved.size() != 0)
	        {
	            boolean fatal = false;
	            for (Iterator<String> it = unresolved.iterator(); it.hasNext();)
	            {
	                String u = it.next();
	                if (!externs.contains( u ))
	                {
	                    ThreadLocalToolkit.log( new LinkerException.UndefinedSymbolException( u ) );
	                    fatal = true;
	                }
	            }
	            if (fatal)
	            {
	                throw new LinkerException.LinkingFailed();
	            }
	        }

        }
        catch (LinkerException e)
        {
            ThreadLocalToolkit.log( e );
            throw e;
        }
    }

	public static String dumpRBList(Set<String> bundles)
	{
		StringBuilder b = new StringBuilder();
	    b.append("bundles = ");
	    for (Iterator<String> iterator = bundles.iterator(); iterator.hasNext();)
	    {
		    String str = iterator.next();
		    b.append(str + " ");
	    }		
	    return b.toString();
	}
	
	private static void mapAll( Map<String, CompilationUnit> map, Set keys, CompilationUnit val )
	{
	    for (Iterator it = keys.iterator(); it.hasNext();)
	    {
	        String defname = (String) it.next();
//            defname = defname.replace( ':', '.' );      // FIXME - which is the canonical form?
	        map.put( defname, val );
	    }
	}

    /**
     * Get the set of metadata names that should be preserved when optimizing this movie. 
     *
     * @return Set of metadata names to keep in the movie.
     */
    public Set<String> getMetadata()
    {
        return metadata;
    }

// todo - move/refactor, this is temporary 'til linkable/script stuff gets hoisted out of Compunit
}