/*
 *
 *  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.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.flex.compiler.common.XMLName;
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.internal.projects.FlexJSProject;
import org.apache.flex.compiler.internal.projects.SourcePathManager;
import org.apache.flex.compiler.problems.ICompilerProblem;
import org.apache.flex.compiler.problems.NoCompilationUnitForDefinitionProblem;
import org.apache.flex.compiler.problems.NoSourceForClassInNamespaceProblem;
import org.apache.flex.compiler.problems.NoSourceForClassProblem;
import org.apache.flex.compiler.projects.IASProject;
import org.apache.flex.compiler.targets.IJSTarget;
import org.apache.flex.compiler.targets.ITargetProgressMonitor;
import org.apache.flex.compiler.targets.ITargetSettings;
import org.apache.flex.compiler.units.ICompilationUnit;
import org.apache.flex.compiler.units.ICompilationUnit.UnitType;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;

public class FlexJSSWCTarget extends JSTarget implements IJSTarget
{
    protected ICompilationUnit mainCU;
    protected RootedCompilationUnits rootedCompilationUnits;

    /**
     * Initialize a JS target with the owner project and root compilation units.
     * 
     * @param project the owner project
     */
    public FlexJSSWCTarget(FlexJSProject project, ITargetSettings targetSettings,
            ITargetProgressMonitor progressMonitor)
    {
        super(project, targetSettings, progressMonitor);
        flexProject = (FlexJSProject)project;
    }

    private FlexJSProject flexProject;
    
    @Override
    protected Target.RootedCompilationUnits computeRootedCompilationUnits() throws InterruptedException
    {
        final Set<ICompilationUnit> rootCompilationUnits = new HashSet<ICompilationUnit>();

        final Collection<File> includedSourceFiles = targetSettings.getIncludeSources();
        final Set<String> includeClassNameSet = ImmutableSet.copyOf(targetSettings.getIncludeClasses());
        final Set<String> includedNamespaces = ImmutableSet.copyOf(targetSettings.getIncludeNamespaces());

        final ArrayList<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
        
        // Select definitions according to configurations.

        // include-namespace
        final Collection<ICompilationUnit> includeNamespaceUnits = 
            getCompilationUnitsForIncludedNamespaces(includedNamespaces, problems); 
        rootCompilationUnits.addAll(includeNamespaceUnits);
        
        // include-class + include-namespace
        rootCompilationUnits.addAll(getCompilationUnitsFromClassNames(null, includeClassNameSet, problems));

        // include-source
        for (final File includedSourceFileName : includedSourceFiles)
        {
            // Get all the compilation units in the project that reference the specified file.
            Collection<ICompilationUnit> compilationUnitsForFile = project.getWorkspace().getCompilationUnits(includedSourceFileName.getAbsolutePath(), project);
            
            // For compilation units with that differ by qname, choose the compilation that
            // appears first on the source-path.
            if (compilationUnitsForFile.size() > 1)
            {
                compilationUnitsForFile = filterUnitsBasedOnSourcePath(compilationUnitsForFile);
            }
            
            for (ICompilationUnit cu : compilationUnitsForFile)
            {
                // IFilter out any compilation unit in the list where the specified file is not the root
                // source file compiled by the compilation unit.
                if (cu.getAbsoluteFilename().equals(includedSourceFileName.getAbsolutePath()))
                    rootCompilationUnits.add(cu);
            }
        }

        //Add compilation units for included resource bundles
        for (ICompilationUnit rbCompUnit : getIncludedResourceBundlesCompilationUnits(problems))
            rootCompilationUnits.add(rbCompUnit);

        // -include and -include-libraries
        rootCompilationUnits.addAll(getIncludesCompilationUnits());
        rootCompilationUnits.addAll(getIncludeLibrariesCompilationUnits());
        
        return new Target.RootedCompilationUnits(rootCompilationUnits, problems);
    }

    /**
     * For compilation units with the same absolute source path, filter based on
     * the source path. The compilation unit found on the highest priority
     * source path wins. The rest of the compilation units with qnames are
     * discared. If a unit is not on the source path or does not have a qname or
     * more than one qname, then let it thru the filter.
     * 
     * @param compilationUnitsForFile list of compilation units to filter.
     * @return filtered compilation units.
     * @throws InterruptedException
     */
    private Collection<ICompilationUnit> filterUnitsBasedOnSourcePath(Collection<ICompilationUnit> compilationUnitsForFile) throws InterruptedException
    {
        List<ICompilationUnit> sourcePathUnits = new ArrayList<ICompilationUnit>(compilationUnitsForFile);
        boolean foundHighestPriorityUnit = false;
        for (File sourcePath : flexProject.getSourcePath())
        {
            for (ICompilationUnit unit : sourcePathUnits)
            {
                // We only care about filtering units on the source path
                // that follow the single definition rule.
                UnitType unitType = unit.getCompilationUnitType();
                if (unitType == UnitType.AS_UNIT || unitType == UnitType.FXG_UNIT ||
                    unitType == UnitType.MXML_UNIT || unitType == UnitType.CSS_UNIT)
                {
                    Collection<String> qnames = unit.getQualifiedNames();
                    if (qnames.size() > 1)
                        continue;
                    
                    String unitQname = qnames.isEmpty() ? "" : qnames.iterator().next();
                    String computedQname = SourcePathManager.computeQName(sourcePath, new File(unit.getAbsoluteFilename()));
                    
                    if (unitQname.equals(computedQname))
                    {
                        // We found a unit on the source path. Only keep the 
                        // first unit found on the source path and remove the 
                        // others.
                        if (foundHighestPriorityUnit)
                            compilationUnitsForFile.remove(unit);
                        
                        foundHighestPriorityUnit = true;
                        break; // should only be one compilation unit on a source path
                    }
                }
            }
        }
        
        return compilationUnitsForFile;
    }

    /**
     * Get the compilation units for the given included namespaces. Also perform error
     * checking.
     * 
     * @param namespaces the namespaces included in this swc target.
     * @param problems A collection where detected problems are added.
     * @return A collection of compilation units.
     * @throws InterruptedException 
     */
    private Collection<ICompilationUnit> getCompilationUnitsForIncludedNamespaces(
            Collection<String> namespaces,
            Collection<ICompilerProblem> problems) throws InterruptedException
    {
        final Collection<ICompilationUnit> allUnits = new HashSet<ICompilationUnit>();
        
        for (String namespace : namespaces)
        {
            // For each namespace get the set of classes. 
            // From the classes get the the compilation units.
            // Validate the compilation units are resolved to source
            // files unless there are lookupOnly entries.
            final Collection<String> includeNamespaceQualifiedNames =
                flexProject.getQualifiedClassNamesForManifestNamespaces(
                        Collections.singleton(namespace));
            final Collection<ICompilationUnit> units = 
                getCompilationUnitsFromClassNames(namespace, includeNamespaceQualifiedNames, problems);
            validateIncludeNamespaceEntries(namespace, units, problems);
            allUnits.addAll(units);
        }
        return allUnits;
    }
    
    /**
     * Validate that the manifest entries in the included namespaces resolve to
     * source files, not classes from other SWCs. The exception is for entries
     * that are "lookupOnly".
     * 
     * @param namespace The target namespace.
     * @param units The compilation units found in that namespace.
     * @param problems detected problems are added to this list.
     * @throws InterruptedException 
     */
    private void validateIncludeNamespaceEntries(String namespace, 
            Collection<ICompilationUnit> units, 
            Collection<ICompilerProblem> problems) throws InterruptedException
    {
        for (ICompilationUnit unit : units)
        {
            List<String> classNames = unit.getQualifiedNames();
            String className = classNames.get(classNames.size() - 1);
            Collection<XMLName> xmlNames = flexProject.getTagNamesForClass(className);
            for (XMLName xmlName : xmlNames)
            {
                if (namespace.equals(xmlName.getXMLNamespace()))
                {
                    if (!flexProject.isManifestComponentLookupOnly(xmlName) && 
                        unit.getCompilationUnitType() == UnitType.SWC_UNIT)
                    {
                        problems.add(new NoSourceForClassInNamespaceProblem(namespace, className));
                    }
                    break;
                }
            }
        }
    }

    /**
     * Return a collection of compilation units for a collection of class names. 
     *
     * @param namespace the namespace of the classes. Null if there is no namespace.
     * @param classNames
     * @param problems detected problems are added to this list.
     * @return a collection of compilation units.
     */
    private Collection<ICompilationUnit> getCompilationUnitsFromClassNames(String namespace,
            Collection<String> classNames,
            final Collection<ICompilerProblem> problems)
    {
        Collection<String> compilableClassNames = new ArrayList<String>();
        for (String className : classNames)
        {
            Collection<XMLName> tagNames = flexProject.getTagNamesForClass(className);
            boolean okToAdd = true;
            for (XMLName tagName : tagNames)
            {
                if (flexProject.isManifestComponentLookupOnly(tagName))
                    okToAdd = false;
            }
            if (okToAdd)
                compilableClassNames.add(className);
        }
        
        // Class names are turned into references and then info compilation units.
        final Iterable<IResolvedQualifiersReference> references = 
            Iterables.transform(compilableClassNames, new Function<String, IResolvedQualifiersReference>()
                {
                    @Override
                    public IResolvedQualifiersReference apply(String qualifiedName)
                    {
                        return ReferenceFactory.packageQualifiedReference(project.getWorkspace(), qualifiedName, true);
                    }
                });

        Collection<ICompilationUnit> units = new LinkedList<ICompilationUnit>();
        for (IResolvedQualifiersReference reference : references)
        {
            IDefinition def = reference.resolve(flexProject);
            if (def == null)
            {
                if (namespace == null)
                    problems.add(new NoSourceForClassProblem(reference.getDisplayString()));
                else
                    problems.add(new NoSourceForClassInNamespaceProblem(namespace, reference.getDisplayString()));
            }
            else
            {
                ICompilationUnit defCU = project.getScope().getCompilationUnitForDefinition(def);
                if (defCU == null)
                    problems.add(new NoCompilationUnitForDefinitionProblem(def.getBaseName()));
                else
                    units.add(defCU);
            }
        }

        return units;
    }


}
