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

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import flex2.compiler.Source;
import flex2.compiler.SourceList;
import flex2.compiler.common.Configuration;
import flex2.compiler.common.Configuration.RslPathInfo;
import flex2.compiler.io.FileUtil;
import flex2.compiler.io.VirtualFile;
import flex2.linker.SimpleMovie;
import flex2.tools.VersionInfo;
import flex2.tools.oem.Message;
import flex2.tools.oem.Report;

/**
 * A Report implementation.
 * 
 * @version 2.0.1
 * @author Clement Wong
 */
public class OEMReport implements Report
{
    public OEMReport(List<Source> sources, SimpleMovie movie, Configuration configuration,
                     SourceList sourceList, String configurationReport, List<Message> messages)
    {
        this(sources, movie, configuration, sourceList, configurationReport, messages, null);
    }
    
    public OEMReport(List<Source> sources, SimpleMovie movie, Configuration configuration,
                     SourceList sourceList, String configurationReport, List<Message> messages,
					 Map<String, VirtualFile> archiveFiles)
	{
        if (sourceList != null)
        {
            sourceListPaths = sourceList.getPaths();
        }

		init(sources, /* null,*/
			 configuration == null ? null : configuration.getResourceBundles(),
			 archiveFiles, configuration);

		//processFrames(movie);
		processMessages(messages);
		
		this.frameCount = 1 ;
		this.configurationReport = configurationReport;
		
		defaultWidth = configuration != null ? configuration.defaultWidth() : 0;
		defaultHeight = configuration != null ? configuration.defaultHeight() : 0;

		width = 0;
		height = 0;
		widthPercent = 0.0;            
		heightPercent = 0.0;
        
        if (movie != null)
		{
			linkReport = movie.getLinkReport();
			sizeReport = movie.getSizeReport();
			bgColor = movie.bgcolor.color;
			pageTitle = movie.pageTitle;
			
			if (movie.userSpecifiedWidth)
			{
				width = movie.width;
			}
			else if (configuration != null)
            {
                String percent = configuration.widthPercent();
                if (percent != null)
                {
                    percent = percent.trim();
                    // Percent character is expected but allow it to be optional.
                    if (percent.length() >= 1 &&
                        percent.charAt(percent.length() - 1) == '%')
                    {
                        percent = percent.substring(0, percent.length() - 1);
                    }
                    try
                    {
                        widthPercent = Double.parseDouble(percent) / 100;
                    }
                    catch(NumberFormatException ex) {}
                }
            }

			if (movie.userSpecifiedHeight)
			{
				height = movie.height;
			}
			else if (configuration != null)
            {
                String percent = configuration.heightPercent();
                if (percent != null)
                {
                    percent = percent.trim();
                    // Percent character is expected but allow it to be optional.
                    if (percent.length() >= 1 &&
                        percent.charAt(percent.length() - 1) == '%')
                    {
                        percent = percent.substring(0, percent.length() - 1);
                    }
                    try
                    {
                        heightPercent = Double.parseDouble(percent) / 100;
                    }
                    catch(NumberFormatException ex) {}
                }
            }
		}
		else
		{
			linkReport = null;
			sizeReport = null;
			bgColor = 0;
			pageTitle = null;
		}
	}
	
	private void init(List<Source> sources, /* List<CompilationUnit> exportedUnits,*/ Set<String> resourceBundles,
	                  Map<String, VirtualFile> archiveFiles,
	                  Configuration configuration)
	{
		TreeSet<String> sourceNames = new TreeSet<String>();
		TreeSet<String> assetNames = new TreeSet<String>();
		TreeSet<String> libraryNames = new TreeSet<String>();
		
		data = new HashMap<String, Data>();
		locations = new HashMap<String, String>();
		
        if (sources != null)
        {
            processSources(sources, sourceNames, assetNames, libraryNames, data, locations);
        }

		timestamps = new HashMap<String, Long>();

        // Store timestamps for each path in the SourceList, so
        // contentUpdated() can report true if new sources are added
        // to the SourceList.
        if (sourceListPaths != null)
        {
            for (File path : sourceListPaths)
            {
                storeTimestamps(path);
            }
        }

		compiler_SourceNames = toArray(sourceNames);
		storeTimestamps(compiler_SourceNames);

		compiler_AssetNames = toArray(assetNames);
		storeTimestamps(compiler_AssetNames);

		compiler_LibraryNames = toArray(libraryNames);
		storeTimestamps(compiler_LibraryNames);
		
		resourceBundleNames = toArray(resourceBundles);

		sourceNames.clear();
		assetNames.clear();
		libraryNames.clear();
		
		//processCompilationUnits(exportedUnits, sourceNames, assetNames, libraryNames);
			
        // Add files to the assets set so they are included in the timestamps.
        // FB calls the OEMReports.contentUpdated() method to determine if a 
		// file has changed and if so it will recompile. This code was added 
		// for the specific case where a default.css file was modified but FB
		// didn't think it needed to recompile because default.css wasn't in
		// the timestamps map.
        if (archiveFiles != null)
        {
            for (String fileName: archiveFiles.keySet())
            {
                assetNames.add(fileName);
            }
        }

		linker_SourceNames = toArray(sourceNames);
		storeTimestamps(linker_SourceNames);

		linker_AssetNames = toArray(assetNames);
		storeTimestamps(linker_AssetNames);

		linker_LibraryNames = toArray(libraryNames);		
		storeTimestamps(linker_LibraryNames);

        // Add libraries linked as RSLs to the timestamp map.
        // Saving the digests of the libraries would be better than a 
        // timestamp since we would know if the digest changed, not
        // just something in the library. We can't compare digests because
        // contentUpdated() does not have access to the swcs we will 
        // compile with. Timestamps may cause us to recompile an app when
        // the RSL has not been modified but that should be pretty rare.
        if (configuration != null)
        {
            List<RslPathInfo> rslPathInfoList = configuration.getRslPathInfo();
            if (rslPathInfoList.size() > 0)
            {
                String[] rslPaths = new String[rslPathInfoList.size()];
                int i = 0;
                for (RslPathInfo rslPathInfo : rslPathInfoList)
                {
                    rslPaths[i++] = rslPathInfo.getSwcVirtualFile().getName();
                }

                storeTimestamps(rslPaths);
            }
        }
	}

    private void storeTimestamps(File path)
    {
        // (SDK-30367) Timestamp caching was added after Flex 3 but it causes
        // performance issues as it also checks files under hidden directories,
        // e.g. .svn. Skipping checking the timestamp of hidden files and
        // folders helps reduce the time spent in this method.
        if (path.isHidden()) 
            return;

        timestamps.put(FileUtil.getCanonicalPath(path), path.lastModified());

        for (File file : path.listFiles())
        {
            if (file.isDirectory())
            {
                storeTimestamps(file);
            }
        }
    }
	
	private void storeTimestamps(String[] a)
	{
        if (a != null)
        {
            for (String fileName : a)
            {
                if ((fileName != null) && !timestamps.containsKey(fileName))
                {
                    timestamps.put(fileName, new File(fileName).lastModified());
                }
            }
        }
	}
	
	private String[] compiler_SourceNames, compiler_AssetNames, compiler_LibraryNames;
	private String[] linker_SourceNames, linker_AssetNames, linker_LibraryNames;
	private String[] resourceBundleNames;
	private Map<String, Data> data;
    private Map<String, String> locations;
    private Map<String, Long> timestamps;
	
	private int frameCount;
	private int bgColor, defaultWidth, defaultHeight, width, height;
	private String pageTitle;
	private double widthPercent, heightPercent;
	
	private String linkReport, sizeReport, configurationReport;
	private Message[] messages;
	
	//private String[][] assetNames, definitionNames;
    private List<File> sourceListPaths;
	
	public boolean contentUpdated()
	{
		for (Iterator<String> i = timestamps.keySet().iterator(); i.hasNext(); )
		{
			String path = i.next();
			Long ts = timestamps.get(path);
			File f = new File(path);
			
			if (!f.exists() || f.lastModified() != ts.longValue())
			{
				return true;
			}
		}
		return false;
	}
	
	public String[] getSourceNames(Object report)
	{
		return (COMPILER.equals(report)) ? compiler_SourceNames : (LINKER.equals(report)) ? linker_SourceNames : null;
	}

	public String[] getAssetNames(int frame)
	{
	    return new String[0];
		//return assetNames[frame - 1];
	}
	
	public String[] getAssetNames(Object report)
	{
		return (COMPILER.equals(report)) ? compiler_AssetNames : (LINKER.equals(report)) ? linker_AssetNames : null;
	}

	public String[] getLibraryNames(Object report)
	{
		return (COMPILER.equals(report)) ? compiler_LibraryNames : (LINKER.equals(report)) ? linker_LibraryNames : null;
	}

	public String[] getResourceBundleNames()
	{
		return resourceBundleNames;
	}
	
	public String[] getDefinitionNames(int frame)
	{
        return new String[0];
		//return definitionNames[frame - 1];
	}
	
	public String[] getDefinitionNames(String sourceName)
	{
		Data d = data.get(sourceName);
		return d == null ? null : d.definitions;
	}
	
	public String getLocation(String definition)
	{
		return locations.get(definition);
	}
	
	public String[] getDependencies(String definition)
	{
		String location = getLocation(definition);
		
		if (location != null)
		{
			Data d = data.get(location);
			return d == null ? null : d.dependencies;
		}
		else
		{
			return null;
		}
	}

	public String[] getPrerequisites(String definition)
	{
		String location = getLocation(definition);
		
		if (location != null)
		{
			Data d = data.get(location);
			return d == null ? null : d.prerequisites;
		}
		else
		{
			return null;
		}
	}
	
	public long writeLinkReport(Writer out) throws IOException
	{
		long size = 0;
		
		if (linkReport != null)
		{
			out.write(linkReport);
			out.flush();
			size = linkReport.length();
		}
		
		return size;
	}
	
	public long writeSizeReport(Writer out) throws IOException
	{
		long size = 0;
		
		if (sizeReport != null)
		{
			out.write(sizeReport);
			out.flush();
			size = sizeReport.length();
		}
		
		return size;
	}

	public long writeConfigurationReport(Writer out) throws IOException
	{
		long size = 0;
		
		if (configurationReport != null)
		{
			out.write(configurationReport);
			out.flush();
			size = configurationReport.length();
		}
		
		return size;
	}
	
	public int getBackgroundColor()
	{
		return bgColor;
	}
	
	public String getPageTitle()
	{
		return pageTitle;
	}
	
	public int getDefaultWidth()
	{
		return defaultWidth;
	}
	
	public int getDefaultHeight()
	{
		return defaultHeight;
	}
	
	public int getWidth()
	{
		return width;
	}
	
	public int getHeight()
	{
		return height;
	}
	
	public double getWidthPercent()
	{
		return widthPercent;
	}
	
	public double getHeightPercent()
	{
		return heightPercent;
	}
	
	public String getCompilerVersion()
	{
		return VersionInfo.buildMessage();
	}

	public Message[] getMessages()
	{
		return messages;
	}
	
	public int getFrameCount()
	{
		return frameCount;
	}
	
	/*
	private void processCompilationUnits(List<CompilationUnit> units, TreeSet<String> sourceNames,
                                         TreeSet<String> assetNames, TreeSet<String> libraryNames)
	{
		for (int i = 0, length = units == null ? 0 : units.size(); i < length; i++)
		{
			CompilationUnit u = units.get(i);
			Source s = (u == null) ? null : u.getSource();
			
			if (s == null)
			{
				continue;
			}
			
			if (s.isFileSpecOwner() || s.isSourceListOwner() || s.isSourcePathOwner() || s.isResourceBundlePathOwner())
			{
				sourceNames.add(s.getName());
				
				for (Iterator j = s.getFileIncludes(); j.hasNext(); )
				{
					VirtualFile f = (VirtualFile) j.next();
					sourceNames.add(f.getName());
				}

				if (u.hasAssets())
                {
                    for (Iterator j = u.getAssets().iterator(); j.hasNext(); )
                    {
                        Map.Entry e = (Map.Entry) j.next();
                        AssetInfo assetInfo = (AssetInfo) e.getValue();
                        VirtualFile path = assetInfo.getPath();
                        if (path != null)
                        {
                            assetNames.add(path.getName());
                        }
                    }
                }
			}
			else if (s.isSwcScriptOwner())
			{
				String location = ((SwcScript) s.getOwner()).getLibrary().getSwcLocation(); 
				libraryNames.add(location);
			}
		}
	}
	*/
	
	private void processSources(List<Source> sources, TreeSet<String> sourceNames, TreeSet<String> assetNames,
                                TreeSet<String> libraryNames, Map<String, Data> data, Map<String, String> locations)
	{
		// use this version for now
		for (Source s : sources)
		{
			sourceNames.add(s.getName());
		}
		/*
		// AJH not sure why all this is needed
		for (Source s : sources)
		{
			CompilationUnit u = (s == null) ? null : s.getCompilationUnit();
			
			if (s == null)
			{
				continue;
			}
			
			if (s.isFileSpecOwner() || s.isSourceListOwner() || s.isSourcePathOwner() || s.isResourceBundlePathOwner())
			{
				sourceNames.add(s.getName());
				
				for (Iterator j = s.getFileIncludes(); j.hasNext(); )
				{
					VirtualFile f = (VirtualFile) j.next();
					sourceNames.add(f.getName());
				}

				if (u.hasAssets())
                {
                    for (Iterator j = u.getAssets().iterator(); j.hasNext(); )
                    {
                        Map.Entry e = (Map.Entry) j.next();
                        AssetInfo assetInfo = (AssetInfo) e.getValue();
                        VirtualFile path = assetInfo.getPath();
                        if (path != null)
                        {
                            assetNames.add(assetInfo.getPath().getName());
                        }
                    }
                }

				if (locations != null)
				{
					for (int j = 0, size = u.topLevelDefinitions.size(); j < size; j++)
					{
						locations.put(u.topLevelDefinitions.get(j).toString(), s.getName());
					}
				}
			}
			else if (s.isSwcScriptOwner())
			{
				String location = ((SwcScript) s.getOwner()).getLibrary().getSwcLocation(); 
				libraryNames.add(location);
				
				if (locations != null)
				{
					for (int j = 0, size = u.topLevelDefinitions.size(); j < size; j++)
					{
						locations.put(u.topLevelDefinitions.get(j).toString(), location);
					}
				}
			}
		}

		for (Source s : sources)
		{
			CompilationUnit u = (s == null) ? null : s.getCompilationUnit();
			
			if (s == null)
			{
				continue;
			}
			
			if (s.isFileSpecOwner() || s.isSourceListOwner() || s.isSourcePathOwner() || s.isResourceBundlePathOwner())
			{
				Data d = new Data();
				d.definitions = toArray(u.topLevelDefinitions);
				d.prerequisites = toArray(u.inheritance, null, locations);
                Set<Name> nameSet = new HashSet<Name>();
                nameSet.addAll(u.namespaces);
                nameSet.addAll(u.types);
                nameSet.addAll(u.expressions);
				d.dependencies = toArray(nameSet, new Set[] { u.extraClasses, u.resourceBundleHistory }, locations);
					
				data.put(s.getName(), d);
			}
		}
		*/
	}

	/*
	private void processFrames(SimpleMovie movie)
	{
		int count = movie == null ? 0 : movie.frames.size();
		assetNames = new String[count][];
		definitionNames = new String[count][];
		
		for (int i = 0; i < count; i++)
		{
			Frame f = movie.frames.get(i);
			List<CompilationUnit> units = movie.getExportedUnitsByFrame(f);
            List<String> aList = new ArrayList<String>(), dList = new ArrayList<String>();
			for (int j = 0, size = units == null ? 0 : units.size(); j < size; j++)
			{
				CompilationUnit u = units.get(j);
				Source s = u.getSource();
				
                if (u.hasAssets())
                {
                    for (Iterator k = u.getAssets().iterator(); k.hasNext(); )
                    {
                        Map.Entry e = (Map.Entry) k.next();
                        AssetInfo assetInfo = (AssetInfo) e.getValue();
                        VirtualFile path = assetInfo.getPath();
                        if (path != null)
                        {
                            String assetName = path.getName();
                            if (!aList.contains(assetName))
                            {
                                aList.add(assetName);
                            }
                        }
					}
				}

				if (s.isFileSpecOwner() || s.isResourceBundlePathOwner() || s.isSourceListOwner() ||
					s.isSourcePathOwner() || s.isSwcScriptOwner())
				{
					for (Iterator k = u.topLevelDefinitions.iterator(); k.hasNext(); )
					{
						String definitionName = k.next().toString();
						dList.add(definitionName);
					}
				}
			}
			
			if (aList.size() > 0)
			{
				assetNames[i] = new String[aList.size()];
				aList.toArray(assetNames[i]);
			}
			
			if (dList.size() > 0)
			{
				definitionNames[i] = new String[dList.size()];
				dList.toArray(definitionNames[i]);
			}
		}
	}
	*/
	private void processMessages(List<Message> messages)
	{
		if (messages != null && messages.size() > 0)
		{
			List<Message> filtered = new ArrayList<Message>();
			
			for (int i = 0, length = messages.size(); i < length; i++)
			{
				Message m = messages.get(i);
				if (m != null && !Message.INFO.equals(m.getLevel()))
				{
					filtered.add(m);
				}
			}
			
			messages = filtered;
		}
			
		if (messages != null && messages.size() > 0)
		{
			this.messages = new Message[messages.size()];
			for (int i = 0, length = this.messages.length; i < length; i++)
			{
				this.messages[i] = new GenericMessage(messages.get(i));
			}
		}
		else
		{
			this.messages = null;
		}
	}
	
	private String[] toArray(Set<String> set)
	{
		String[] a = new String[set == null ? 0 : set.size()];
		int j = 0;
		
		if (set != null)
		{
            for (String source : set)
			{
				a[j++] = source;
			}
		}
		
		return a.length == 0 ? null : a;
	}

	/*
	private String[] toArray(QNameList definitions)
	{
		String[] a = new String[definitions == null ? 0 : definitions.size()];
		
		for (int i = 0; i < a.length; i++)
		{
			a[i] = definitions.get(i).toString();
		}
		
		return a.length == 0 ? null : a;
	}

	private String[] toArray(Set<Name> nameSet, Set[] sets, Map locations)
	{
		TreeSet<String> set = new TreeSet<String>();
		
        for (Name name : nameSet)
		{
            String qName = null;
            if (name instanceof QName && (locations == null || locations.containsKey(qName = name.toString())))
            {
                set.add(qName);
            }
        }

		for (int i = 0, length = sets == null ? 0 : sets.length; i < length; i++)
		{
			if (sets[i] != null)
			{
				for (Object obj : sets[i])
				{
					if ((obj instanceof String) && (locations == null || locations.containsKey(obj)))
					{
						set.add((String)obj);
					}
				}
			}
		}

		return toArray(set);
	}
    */
	static class Data
	{
		String[] definitions;
		String[] prerequisites;
		String[] dependencies;
	}
}
