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

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import macromedia.asc.util.ContextStatics;

import flash.localization.LocalizationManager;
import flash.swf.Frame;
import flash.swf.Movie;
import flash.swf.MovieDecoder;
import flash.swf.MovieEncoder;
import flash.swf.TagDecoder;
import flash.swf.TagEncoder;
import flash.swf.tags.DefineTag;
import flash.util.Trace;
import flex2.compiler.CompilerSwcContext;
import flex2.compiler.io.LocalFile;
import flex2.compiler.io.VirtualFile;
import flex2.compiler.swc.SwcCache;
import flex2.compiler.util.MimeMappings;
import flex2.compiler.util.NameMappings;
import flex2.compiler.util.OrderedProperties;
import flex2.compiler.util.QName;
import flex2.compiler.util.SwcDependencyInfo;
import flex2.compiler.util.SwcDependencyUtil;
import flex2.compiler.util.SwcExternalScriptInfo;
import flex2.compiler.util.ThreadLocalToolkit;
import flex2.compiler.util.Benchmark.MemoryUsage;
import flex2.compiler.util.graph.Vertex;
import flex2.tools.oem.OEMException.CircularLibraryDependencyException;
import flex2.tools.oem.internal.OEMUtil;

/**
 * A utility class, which supports querying for Application, Library,
 * Component, and Script information, loading properties, optimizing,
 * and querying dependency info.
 * @version 3.0
 */
public class Toolkit
{
	/**
	 * 
	 * @param application
	 * @return
	 */
	public static ApplicationInfo getApplicationInfo(File application)
	{
		InputStream in = null;
		ApplicationInfo info = null;
		
		try
		{
			in = new BufferedInputStream(new FileInputStream(application));
			
			Movie movie = new Movie();
			new TagDecoder(in).parse(new MovieDecoder(movie));
			
			info = new ApplicationInfoImpl(movie);
		}
		catch (IOException ex)
		{
            if (Trace.error)
            {
                ex.printStackTrace();
            }
		}
		finally
		{
			try { if (in != null) in.close(); } catch (IOException ex) {}
		}

		return info;
	}

	/**
	 * 
	 * @param library
	 * @return
	 */
	public static LibraryInfo getLibraryInfo(File library)
	{
		return getLibraryInfo(new File[] { library });
	}
	
	/**
	 * 
	 * @param libraries
	 * @return
	 */
	public static LibraryInfo getLibraryInfo(File[] libraries)
	{
		return getLibraryInfo(libraries, false);
	}

	/**
	 * 
	 * @param libraries
	 * @param includeBytecodes
	 * @return
	 */
	public static LibraryInfo getLibraryInfo(File[] libraries, boolean includeBytecodes)
	{
		LibraryInfo info = null;

        try
        {
        	OEMUtil.init(OEMUtil.getLogger(null, new ArrayList<Message>()), new MimeMappings(), null, null, null);
        	
            CompilerSwcContext swcContext = new CompilerSwcContext();
            SwcCache cache = new SwcCache();

            swcContext.load(toVirtualFiles(libraries),
	        				new NameMappings(),
	        				".properties",
	        				cache);
            
            info = new LibraryInfoImpl(swcContext, includeBytecodes);
            
            swcContext.close();
        }
        catch (Throwable t)
        {
            if (Trace.error)
            {
                t.printStackTrace();
            }
        }
        finally
        {
        	OEMUtil.clean();
        }

		return info;
	}
	
	/**
	 * Converts a list of File(s) into a list of VirtualFile(s).
	 * The VirtualFile implementation is flex2.compiler.io.LocalFile.
	 * 
	 * @param files
	 * @return
	 */
	private static VirtualFile[] toVirtualFiles(File[] files)
	{
		if (files == null) return null;
		
		List<VirtualFile> vFiles = new ArrayList<VirtualFile>(files.length);
		for (int i = 0; i < files.length; i++)
		{
		    if (files[i] != null)
		        vFiles.add(new LocalFile(files[i]));
		}
		
		return vFiles.toArray(new VirtualFile[vFiles.size()]);
	}

	/**
	 * Creates a <code>java.util.Properties</code> object from an <code>UTF-8</code> encoded input stream.
	 * 
	 * @param in <code>java.io.InputStream</code>
	 * @return an instance of <code>java.util.Properties</code>;
	 * 						  <code>null</code> if <code>IOException</code> occurs.
	 */
	public static Properties loadProperties(InputStream in)
	{
		return loadProperties(in, "UTF-8");
	}
	
	/**
	 * Creates a <code>java.util.Properties</code> object from an <code>UTF-8</code> encoded .properties file.
	 * 
	 * @param f an <code>UTF-8</code> encoded .properties file
	 * @return an instance of <code>java.util.Properties</code>;
	 * 						  <code>null</code> if the file doesn't exist or if <code>IOException</code> occurs.
	 */
	public static Properties loadProperties(File f)
	{
		return loadProperties(f, "UTF-8");
	}
	
	/**
	 * Creates a <code>java.util.Properties</code> object from an <code>UTF-8</code> encoded .properties file.
	 * 
	 * @param f an <code>UTF-8</code> encoded .properties file
	 * @param encoding character encoding
	 * @return an instance of <code>java.util.Properties</code>;
	 * 						  <code>null</code> if the file doesn't exist or if <code>IOException</code> occurs.
	 */
	public static Properties loadProperties(File f, String encoding)
	{
		if (f != null && f.isFile())
		{
			try
			{
				return loadProperties(new FileInputStream(f), encoding);
			}
			catch (IOException ex)
			{
				return null;
			}
		}
		else
		{
			return null;
		}
	}
	
	private static Properties loadProperties(InputStream in, String encoding)
	{
		if (in != null)
		{
			try
			{
				OrderedProperties p = new OrderedProperties();
				p.load(new BufferedReader(new InputStreamReader(in, encoding)));
				return p;
			}
			catch (IOException ex)
			{
				return null;
			}
		}
		else
		{
			return null;
		}
	}
	
	/**
	 * Optimizes a SWF. This operation performs the following:
	 * 
	 * <pre>
	 * 1. remove debug tags and opcodes
	 * 2. merge abc bytecodes
	 * 3. peephole optimization
	 * 4. remove unwanted metadata
	 * </pre>
	 * 
	 * @param in a SWF input stream
	 * @param out a SWF output stream
	 * @return the number of bytes written to the output stream; <code>0</code> if the optimization fails.
	 */
	public static long optimize(InputStream in, OutputStream out)
	{
		try
		{
			return flex2.tools.WebTierAPI.optimize(in, out);
		}
		catch (IOException ex)
		{
			return 0;
		}
	}
	
	/**
	 * Optimizes the library SWF. This operation performs the following:
	 * 
	 * <pre>
	 * 1. remove debug tags and opcodes
	 * 2. merge abc bytecodes
	 * 3. peephole optimization
	 * 4. remove unwanted metadata, but preserve the metadata specified in the Library object
	 * </pre>
	 * 
	 * This operation returns an optimized version of the library SWF. The SWF in the library
	 * remains unchanged.
	 * 
	 * @param lib a SWF input stream
	 * @param out a SWF output stream
	 * @return the number of bytes written to the output stream; <code>0</code> if the optimization fails.
	 */
	public static long optimize(Library lib, OutputStream out)
	{
		if (lib == null || lib.data == null || lib.data.movie == null) return 0;
		
		try
		{
			TagEncoder handler = new TagEncoder();
			MovieEncoder encoder = new MovieEncoder(handler);
			encoder.export(lib.data.movie);
            
            //TODO PERFORMANCE: A lot of unnecessary recopying here
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			handler.writeTo(baos);

			return flex2.tools.WebTierAPI.optimize(new ByteArrayInputStream(baos.toByteArray()),
											out,
											lib.data.configuration);
		}
		catch (IOException ex)
		{
			return 0;
		}
	}
	
	/**
	 * 
	 *
	 */
	public static void printMemoryUsage()
	{
	    MemoryUsage mem = new flex2.compiler.util.Benchmark().getMemoryUsageInBytes();
	    long mbHeapUsed = (mem.heap / 1048576);
		long mbNonHeapUsed = (mem.nonHeap / 1048576);
		System.out.println("Heap: " + mbHeapUsed + " Non-Heap: " + mbNonHeapUsed);
	}

	// added for FB code model
    /**
     * Returns a list filled with namespaces that should be automatically
     * opened, based on the current target player, e.g. flash10, AS3.
     * 
     * @param targetPlayerMajorVersion E.g. 9, 10, ...
     * @return List<String> containing the namespaces
     */
    public static List<String> getRequiredUseNamespaces(int targetPlayerMajorVersion)
    {
        return ContextStatics.getRequiredUseNamespaces(targetPlayerMajorVersion);
    }
    

    /**
     *  The types of dependency the compiler assigns to a symbol. The possible
     *  values are as follows:
     *  
     *  <ul>
     *  <li>INHERITANCE 
     *  <li>NAMESPACE
     *  <li>SIGNATURE
     *  <li>EXPRESSION
     *  </ul>
     */
    public enum DependencyType {
        /**
         *  The class is used as a base class or is implemented by another 
         *  class.
         */
        INHERITANCE ("i"),
        
        /**
         *  The symbol is a namespace.
         */
        NAMESPACE   ("n"),
        
        /**
         *  The symbol is used in a function signature. 
         */
        SIGNATURE   ("s"),
        
        /**
         *  The symbol is used in a class or function.
         */
        EXPRESSION  ("e");
        
        
        private final String dependency;
        
        DependencyType(String dependency)
        {
            this.dependency = dependency;
        }

        /**
         *  @return A string that represents the dependency type.
         */
        @Override
        public String toString() 
        {
            return dependency;
        }
        
    }
    
    /**
     * Get the dependency order of a given set of libraries.
     * 
     * @param libraries The set of libraries to find the dependency information for. Each
     * File in the list must be a library file or a directory of libraries files.
     * 
     * @return An ordered list of library dependencies. Each String in the 
     * list is the location of a library in the file system. The first library in the list has no
     * dependencies. Each library in the list has at least the same dependencies as its 
     * predecessor and may be dependent on its predecessor as well. 
     */
    public static List<String> getDependencyOrder(File[] libraries) throws CircularLibraryDependencyException
    {
        return getDependencyOrder(libraries, null);
    }

    /**
     * Get the dependency order of a given set of libraries.
     * 
     * @param libraries The set of libraries to find the dependency information for. Each
     * File in the list must be a library file or a directory of libraries files.
     * @param dependencySet The types of dependencies to consider when 
     * determining the dependency order. If this parameter is null or an empty set, then all
     * dependencies will be considered. 
     * 
     * @return An ordered list of library dependencies. Each String in the 
     * list is the location of a library in the file system. The first library in the list has no
     * dependencies. Each library in the list has at least the same dependencies as its 
     * predecessor and may be dependent on its predecessor as well. 
     */
    public static List<String> getDependencyOrder(File[] libraries, 
            EnumSet<DependencyType> dependencySet) throws CircularLibraryDependencyException
    {
        if (libraries == null)
            return Collections.emptyList();
        
        // Convert dependencies from an array of DependencyType to an
        // array of String.
        String[] stringDependencyTypes = dependencyEnumSetToStringArray(dependencySet);
        SwcDependencyInfo info = SwcDependencyUtil.getSwcDependencyInfo(toVirtualFiles(libraries), 
                                                                        stringDependencyTypes,
                                                                        true);
        Set<Vertex<String, SwcExternalScriptInfo>> cycles = info.detectCycles();
        if (cycles.size() > 0) 
        {
            LocalizationManager i10n = ThreadLocalToolkit.getLocalizationManager();
            if (i10n == null)
            {
                OEMUtil.setupLocalizationManager();
                i10n = ThreadLocalToolkit.getLocalizationManager();
            }
            
            String message = i10n.getLocalizedTextString(new CircularLibraryDependencyException(null, null));
            throw new CircularLibraryDependencyException(message, 
                            SwcDependencyUtil.SetOfVertexToString(cycles));
        }
        
        return info.getSwcDependencyOrder();
    }
    
    /**
     * Get the set of library dependencies of a given library.
     * 
     * @param libraries The set of libraries need to resolve all the dependencies of the targetLibrary. Each
     * File in the list must be a library file or a directory of libraries files.
     * @param targetLibrary The libraries to find dependencies for.
     * @param minimizeDependencySet If false, all of the libraries dependencies are returned. If true, the external script
     * classes are reviewed. If the set of script classes resolved in a libraryA is a subset of the script
     * classes resolved in libraryB, then libraryA will be removed as a dependency of targetLibrary.
     * @return A set of Strings; where each String is the location of a library in the file system. 
     */
    public static Set<String> getLibraryDependencies(File[] libraries, 
            File targetLibrary, 
            boolean minimizeDependencySet) throws CircularLibraryDependencyException 
    {
        return getLibraryDependencies(libraries, targetLibrary, minimizeDependencySet, null);
    }
    
    /**
     * Get the set of library dependencies of a given library.
     * 
     * @param libraries The set of libraries need to resolve all the dependencies of the targetLibrary. Each
     * File in the list must be a library file or a directory of libraries files.
     * @param targetLibrary The libraries to find dependencies for.
     * @param minimizeDependencySet If false, all of the libraries dependencies are returned. If true, the external script
     * classes are reviewed. If the set of script classes resolved in a libraryA is a subset of the script
     * classes resolved in libraryB, then libraryA will be removed as a dependency of targetLibrary.
     * @param dependencySet The types of dependencies to consider when 
     * determining the library's dependencies. If this parameter is null or an empty set, then all
     * dependencies will be considered. 
     * @return A set of Strings; where each String is the location of a library in the file system. 
     */
    public static Set<String> getLibraryDependencies(File[] libraries, 
            File targetLibrary, 
            boolean minimizeDependencySet,
            EnumSet<DependencyType> dependencySet) throws CircularLibraryDependencyException
    {
        if (libraries == null || targetLibrary == null)
            return Collections.emptySet();
        
        // Convert dependencies from an array of DependencyType to an
        // array of String.
        String[] stringDependencyTypes = dependencyEnumSetToStringArray(dependencySet);
        SwcDependencyInfo info = SwcDependencyUtil.getSwcDependencyInfo(toVirtualFiles(libraries), 
                                                                        stringDependencyTypes,
                                                                        minimizeDependencySet);
        Set<Vertex<String, SwcExternalScriptInfo>> cycles = info.detectCycles();
        if (cycles.size() > 0) 
        {
            LocalizationManager i10n = ThreadLocalToolkit.getLocalizationManager();
            if (i10n == null)
            {
                OEMUtil.setupLocalizationManager();
                i10n = ThreadLocalToolkit.getLocalizationManager();
            }
            
            String message = i10n.getLocalizedTextString(new CircularLibraryDependencyException(null, null));
            throw new CircularLibraryDependencyException(message, 
                            SwcDependencyUtil.SetOfVertexToString(cycles));
        }

        VirtualFile virtualLibrary = new LocalFile(targetLibrary);
        return info.getDependencies(virtualLibrary.getName());
    }

    /**
     * Convert an EnumSet of DependencyType to an Array of Strings. 
     * 
     * @param dependencySet EnumSet of dependencies to convert.
     * @return Array of Strings. Each string in the Array represents a type of
     * dependency. Returns null if dependencySet is null or an empty set.
     */
    private static String[] dependencyEnumSetToStringArray(EnumSet<DependencyType> dependencySet)
    {
        // Convert dependencies from an array of DependencyType to an
        // array of String.
        String[] stringDependencyTypes = null;
        if (dependencySet != null && dependencySet.size() > 0)
        {
            int n = dependencySet.size();
            int i = 0;
            stringDependencyTypes = new String[n];
            
            for (DependencyType dependency : dependencySet)
            {
                stringDependencyTypes[i++] = dependency.toString();
            }
        }
        
        return stringDependencyTypes;
    }

}


/**
 * 
 *
 */
class ApplicationInfoImpl implements ApplicationInfo
{
    ApplicationInfoImpl(Movie movie)
    {
        version = movie.version;
        
        List frames = movie.frames;
        Set<String> symbols = new TreeSet<String>();
        
        for (int i = 0, size = frames == null ? 0 : frames.size(); i < size; i++)
        {
            Frame f = (Frame) frames.get(i);
            for (Iterator j = f.exportIterator(); j.hasNext(); )
            {
                DefineTag t = (DefineTag) j.next();
                if (t.name != null)
                {
                    symbols.add(t.name);
                }
            }
        }
        
        symbols.toArray(symbolNames = new String[symbols.size()]);
    }
    
    private String[] symbolNames;
    private int version;

    public String[] getSymbolNames()
    {
        return symbolNames;
    }
    
    public int getSWFVersion()
    {
        return version;
    }
}


/**
 * 
 *
 */
class LibraryInfoImpl implements LibraryInfo
{
    LibraryInfoImpl(CompilerSwcContext swcContext, boolean includeBytecodes)
    {
        List<QName> names = new ArrayList<QName>();
        
        for (Iterator i = swcContext.getDefinitionIterator(); i.hasNext(); )
        {
            names.add((QName) i.next());
        }
        
        definitionNames = new String[names.size()];
        
        for (int i = 0; i < definitionNames.length; i++)
        {
            definitionNames[i] = names.get(i).toString();
        }
        
        scripts = new TreeMap<String, Script>();
        
        for (int i = 0; i < definitionNames.length; i++)
        {
            QName def = names.get(i);
            Script s = swcContext.getScript(def, includeBytecodes);
            scripts.put(def.toString(), s);
        }
        
        components = new TreeMap<String, Component>();
        
        for (Iterator i = swcContext.getComponentIterator(); i.hasNext(); )
        {
            Component c = (Component) i.next();
            components.put(c.getClassName(), c);
        }
        
        mappings = swcContext.getNameMappings();
        
        fileNames = new TreeSet<String>(swcContext.getFiles().keySet());
    }
    
    private String[] definitionNames;
    private Map<String, Script> scripts;
    private Map<String, Component> components;
    private NameMappings mappings;
    private Set<String> fileNames;

    public Component getComponent(String namespaceURI, String name)
    {
        return getComponent(mappings.lookupClassName(namespaceURI, name));
    }

    public Component getComponent(String definition)
    {
        return (definition != null) ? components.get(definition) : null;
    }

    public Iterator<Component> getComponents()
    {
        return components.values().iterator();
    }

    public String[] getDefinitionNames()
    {
        return definitionNames;
    }

    public Script getScript(String definition)
    {
        return scripts.get(definition);
    }

    public Iterator<Script> getScripts()
    {
        return scripts.values().iterator();
    }
    
    public Iterator<String> getFiles()
    {
        return fileNames.iterator();
    }
}
