/*
 * 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.netbeans.modules.projectimport.eclipse.core;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import org.netbeans.modules.projectimport.eclipse.core.spi.DotClassPathEntry;
import org.netbeans.modules.projectimport.eclipse.core.spi.Facets;
import org.netbeans.modules.projectimport.eclipse.core.spi.ProjectTypeFactory;
import org.netbeans.modules.projectimport.eclipse.core.spi.ProjectTypeFactory.ProjectDescriptor;
import org.netbeans.spi.project.support.ant.EditableProperties;
import org.netbeans.spi.project.support.ant.PropertyUtils;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;

/**
 * Represents Eclipse project structure.
 *
 * @author mkrauskopf
 */
public final class EclipseProject implements Comparable {

    /** Logger for this class. */
    private static final Logger logger =
            Logger.getLogger(EclipseProject.class.getName());
    
    private static final Lookup.Result<? extends ProjectTypeFactory> projectTypeFactories =
        Lookup.getDefault().lookupResult (ProjectTypeFactory.class);
    
    private Boolean importSupported;
    private ProjectTypeFactory projectFactory;
    private Set<EclipseProject> projectsWeDependOn;
    
    static final String PROJECT_FILE = ".project"; // NOI18N
    static final String CLASSPATH_FILE = ".classpath"; // NOI18N
    
    private Workspace workspace;
    
    private String name;
    private boolean internal = true;
    private DotClassPath cp;
    private Set<String> natures;
    private List<Link> links;
    
    private final File projectDir;
    private final File cpFile;
    private final File prjFile;
    private String jdkDirectory;
    
    private List<String> importProblems = new ArrayList<String>();
    
    private Facets projectFacets;
    
    /**
     * Returns <code>EclipseProject</code> instance representing Eclipse project
     * found in the given <code>projectDir</code>. If a project is not found in
     * the specified directory, <code>null</code> is returned.
     *
     * @return either a <code>EclipseProject</code> instance or null if a given
     *      <code>projectDir</code> doesn't contain valid Eclipse project.
     */
    static EclipseProject createProject(File projectDir) {
        if (!EclipseUtils.isRegularProject(projectDir)) {
            logger.fine(projectDir + " doesn't contain regular Eclipse project."); // NOI18N
            return null;
        }
        return new EclipseProject(projectDir);
    }
    
    /** Sets up a project directory. */
    /*private*/ EclipseProject(File projectDir) {
        this.projectDir = projectDir;
        File f = new File(projectDir, CLASSPATH_FILE);
        this.cpFile = f.exists() ? f : null;
        this.prjFile = new File(projectDir, PROJECT_FILE);
    }

    void removeInvalidSourceRoots(List<String> projectImportProblems) {
        List<DotClassPathEntry> projectSources = new ArrayList<DotClassPathEntry>();
        for (DotClassPathEntry e : getSourceRoots()) {
            if (new File(e.getAbsolutePath()).exists()) {
                projectSources.add(e);
            } else {
                projectImportProblems.add(
                    NbBundle.getMessage(EclipseProject.class, "MSG_InvalidSourceRoot", e.getRawPath())); //NOI18N
            }
        }
        cp.updateSourceRoots(projectSources);
    }

    void setFacets(Facets projectFacets) {
        this.projectFacets = projectFacets;
    }

    public Facets getFacets() {
        return projectFacets;
    }

    void setLinks(List<Link> links) {
        this.links = links;
    }

    List<Link> getLinks() {
        return links;
    }


    void setNatures(Set<String> natures) {
        this.natures = natures;
    }
    
    void setWorkspace(Workspace workspace) {
        this.workspace = workspace;
    }
    
    public Workspace getWorkspace() {
        return workspace;
    }
    
    void setClassPath(DotClassPath cp) {
        this.cp = cp;
        calculateAbsolutePaths();
        convertFileVariablesToFolderVariables();
        updateSourcePathAttribute();
        updateJavadocLocationAttribute();
        try {
            resolveContainers(new ArrayList<String>(), false);
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    }
    
    public List<DotClassPathEntry> getClassPathEntries() {
        return cp.getClassPathEntries();
    }
    
    /**
     * Returns project's name.
     */
    public String getName() {
        return name;
    }
    
    void setName(String name) {
        this.name = name;
    }
    
    void setInternal(boolean internal) {
        this.internal = internal;
    }
    
    public boolean isInternal() {
        return internal;
    }
    
    public File getDirectory() {
        return projectDir;
    }
    
    /**
     * Returns metadata file containing information about this projects. I.e.
     * normally <em>.project</em> file withing the project's directory. See
     * {@link #PROJECT_FILE}.
     */
    File getProjectFile() {
        return prjFile;
    }
    
    /**
     * Returns metadata file containing information about this projects. I.e.
     * normally <em>.classpath</em> file withing the project's directory. See
     * {@link #CLASSPATH_FILE}.
     */
    File getClassPathFile() {
        return cpFile;
    }
    
    public Set<String> getNatures() {
        return natures;
    }
    
    /**
     * Can this Eclipse project be converted to NetBeans or not?
     */
    public boolean isImportSupported() {
        performRecognitionIfNeeded();
        return importSupported.booleanValue();
    }
    
    public ProjectTypeFactory getProjectTypeFactory() {
        performRecognitionIfNeeded();
        return projectFactory;
    }

    private ProjectDescriptor getProjectDescriptor() {
        return new ProjectTypeFactory.ProjectDescriptor(getDirectory(), natures, projectFacets);
    }
    
    File  getProjectFileLocation(String token) {
        if (!isImportSupported()) {
            return null;
        }
        return getProjectTypeFactory().getProjectFileLocation(getProjectDescriptor(), token);
    }
    
    private void performRecognitionIfNeeded() {
        if (importSupported == null) {
            importSupported = Boolean.FALSE;
            for (ProjectTypeFactory factory : projectTypeFactories.allInstances()) {
                if (factory.canHandle(getProjectDescriptor())) {
                    this.projectFactory = factory;
                    importSupported = Boolean.TRUE;
                    break;
                }
            }
        }
    }
    
    /**
     * Returns JDK directory for platform this project uses. Can be null in a
     * case when a JDK was set for an eclipse project in Eclipse then the
     * directory with JDK was deleted from filesystem and then a project is
     * imported to NetBeans.
     *
     * @return JDK directory for the project
     */
    public String getJDKDirectory() {
        if (jdkDirectory == null && workspace != null && cp.getJREContainer() != null) {
            logger.finest("Getting JDK directory for project " + this.getName()); // NOI18N
            jdkDirectory = workspace.getJDKDirectory(cp.getJREContainer().getRawPath());
            logger.finest("Resolved JDK directory: " + jdkDirectory); // NOI18N
            // jdkDirectory = workspace.getJDKDirectory(projectDir.getName());
        }
        return jdkDirectory;
    }
    
    /** Convenient delegate to <code>ClassPath</code> */
    public List<DotClassPathEntry> getSourceRoots() {
        return cp.getSourceRoots();
    }
    
    /**
     * Returns collection of <code>EclipseProject</code> this project requires.
     */
    public Set<EclipseProject> getProjects() {
        if (workspace != null && projectsWeDependOn == null) {
            projectsWeDependOn = new HashSet<EclipseProject>();
            for (DotClassPathEntry entry : getClassPathEntries()) {
                if (entry.getKind() != DotClassPathEntry.Kind.PROJECT) {
                    continue;
                }
                EclipseProject prj = workspace.getProjectByRawPath(entry.getRawPath());
                if (prj != null) {
                    projectsWeDependOn.add(prj);
                }
            }
        }
        return projectsWeDependOn == null ?
            Collections.<EclipseProject>emptySet() : projectsWeDependOn;
    }

    void resolveContainers(List<String> importProblems, boolean importInProgress) throws IOException {
        for (DotClassPathEntry entry : cp.getClassPathEntries()) {
            if (entry.getKind() != DotClassPathEntry.Kind.CONTAINER) {
                continue;
            }
            ClassPathContainerResolver.resolve(workspace, entry, importProblems, importInProgress);
        }
    }
    
    void replaceContainers() {
        List<DotClassPathEntry> newCp = new ArrayList<DotClassPathEntry>();
        for (DotClassPathEntry entry : cp.getClassPathEntries()) {
            if (entry.getKind() != DotClassPathEntry.Kind.CONTAINER) {
                newCp.add(entry);
                continue;
            }
            List<DotClassPathEntry> repl = ClassPathContainerResolver.replaceContainerEntry(this, workspace, entry, importProblems);
            if (repl != null) {
                newCp.addAll(repl);
            } else {
                newCp.add(entry);
            }
        }
        cp.updateClasspath(newCp);
    }
    
    void setupEnvironmentVariables(List<String> importProblems) throws IOException {
        if (workspace == null) {
            return;
        }
        EditableProperties ep = PropertyUtils.getGlobalProperties();
        boolean changed = false;
        for (DotClassPathEntry entry : cp.getClassPathEntries()) {
            if (entry.getKind() != DotClassPathEntry.Kind.VARIABLE) {
                continue;
            }
            String s = EclipseUtils.splitVariable(entry.getRawPath())[0];
            Workspace.Variable v = getVariable(s);
            if (v != null) {
                s = "var."+PropertyUtils.getUsablePropertyName(s); //NOI18N
                if (ep.getProperty(s) == null) {
                    ep.setProperty(s, v.getLocation());
                    changed = true;
                } else if (!ep.getProperty(s).equals(v.getLocation())) {
                    importProblems.add(org.openide.util.NbBundle.getMessage(EclipseProject.class, "MSG_IDEVariableMismatch", s, ep.getProperty(s), v.getLocation())); //NOI18N
                }
            } else {
                importProblems.add(org.openide.util.NbBundle.getMessage(EclipseProject.class, "MSG_IDEVariableNotFound", s)); //NOI18N
                ep.setProperty(s, ""); //NOI18N
                changed = true;
            }
        }
        if (changed) {
            PropertyUtils.putGlobalProperties(ep);
        }
    }
    
    void convertFileVariablesToFolderVariables() {
        if (workspace == null) {
            return;
        }
        for (DotClassPathEntry entry : cp.getClassPathEntries()) {
            if (entry.getKind() != DotClassPathEntry.Kind.VARIABLE) {
                continue;
            }
            String s = EclipseUtils.splitVariable(entry.getRawPath())[0];
            Workspace.Variable v = getVariable(s);
            if (v != null && v.isFileVariable()) {
                // convert eclipse file variable to folder variable
                entry.updateVariableValue(v.getName()+'/'+v.getFileName());
            }
        }
    }
    
    private void updateSourcePathAttribute() {
        if (workspace == null) {
            return;
        }
        for (DotClassPathEntry entry : cp.getClassPathEntries()) {
            String sourcePath = entry.getProperty(DotClassPathEntry.ATTRIBUTE_SOURCEPATH);
            if (sourcePath == null) {
                continue;
            }
            String resolvedPath = resolveSourcePathAttribute(sourcePath, workspace, true);
            if (resolvedPath != null) {
                entry.updateSourcePath(resolvedPath);
            }
        }
    }
    
    static String resolveSourcePathAttribute(String sourcePath, Workspace workspace, boolean useVariables) {
        String resolvedPath = resolvePath(sourcePath, workspace);
        if (resolvedPath != null) {
            return resolvedPath;
        }
        // test whether sourcePath starts with variable:
        for (Workspace.Variable v : workspace.getVariables()) {
            if (sourcePath.startsWith(v.getName())) {
                String s[] = EclipseUtils.splitVariable(sourcePath);
                // change value to Ant style property directly usable in NB:
                if (useVariables) {
                    return "${"+s[0]+"}"+s[1]; // NOI18N
                } else {
                    return v.getLocation() + s[1];
                }
            }
        }
        return null;
    }
    
    private void updateJavadocLocationAttribute() {
        for (DotClassPathEntry entry : cp.getClassPathEntries()) {
            String javadoc = entry.getProperty(DotClassPathEntry.ATTRIBUTE_JAVADOC);
            if (javadoc == null) {
                continue;
            }
            entry.updateJavadoc(resolveJavadocLocationAttribute(javadoc, workspace, importProblems, false));
        }
    }
    
    static String resolveJavadocLocationAttribute(String javadoc, Workspace workspace, List<String> importProblems, boolean returnURL) {
        String jarPath = null;
        // strip off jar protocol; because of 'platform' protocol which is 
        // undefined in NB the FileUtil.getArchiveFile will not be used here
        if (javadoc.startsWith("jar:")) { // NOI18N
            jarPath = javadoc.substring(javadoc.indexOf("!/")); //NOI18N
            if (!jarPath.endsWith("/")) { //NOI18N
                jarPath += "/"; //NOI18N
            }
            javadoc = javadoc.substring(4, javadoc.indexOf("!/")); //NOI18N
        }
        if (javadoc.startsWith("platform:/resource")) { // NOI18N
            if (workspace == null) {
                importProblems.add(org.openide.util.NbBundle.getMessage(EclipseProject.class, "MSG_WorkspaceDependentProtocol", javadoc)); //NOI18N
                return null;
            }
            String s = resolvePath(javadoc.substring(18), workspace);
            if (s != null) {
                if (returnURL) {
                    try {
                        s = Utilities.toURI(new File(s)).toURL().toExternalForm();
                        if (jarPath != null) {
                            s = "jar:"+s+jarPath;
                        }
                        return s;
                    } catch (MalformedURLException ex) {
                        Exceptions.printStackTrace(ex);
                        return null;
                    }
                } else {
                    if (jarPath != null) {
                        s += jarPath;
                    }
                    return s;
                }
            }
        }
        if (javadoc.startsWith("platform")) { // NOI18N
            importProblems.add(org.openide.util.NbBundle.getMessage(EclipseProject.class, "MSG_UnsupportedProtocol", javadoc)); //NOI18N
            return null;
        }
        // copied from FileUtil.getArchiveFile
        if (javadoc.indexOf("file://") > -1 && javadoc.indexOf("file:////") == -1) {  //NOI18N
            /* Replace because JDK application classloader wrongly recognizes UNC paths. */
            javadoc = javadoc.replaceFirst("file://", "file:////");  //NOI18N
        }
        URL u;
        try {
            u = new URL(javadoc);
        } catch (MalformedURLException ex) {
            importProblems.add(org.openide.util.NbBundle.getMessage(EclipseProject.class, "MSG_UnsupportedJavadocLocation", javadoc));
            return null;
        }
        if (!"file".equals(u.getProtocol())) { // NOI18N
            // XXX this is just a warning rather then import problem
            // Perhaps instead of List<String> for import problems define
            // a class which could have two lists: import problems and import warnings
            importProblems.add(org.openide.util.NbBundle.getMessage(EclipseProject.class, "MSG_UnsupportedProtocol", u.toExternalForm()));
            return null;
        }
        try {
            if (returnURL) {
                if (jarPath != null) {
                    return "jar:"+u.toExternalForm()+jarPath;
                } else {
                    return u.toExternalForm();
                }
            } else {
                File f = Utilities.toFile(u.toURI());
                String path = f.getPath();
                if (jarPath != null) {
                    path += jarPath;
                }
                return path;
            }
        } catch (URISyntaxException ex) {
            importProblems.add(org.openide.util.NbBundle.getMessage(EclipseProject.class, "MSG_JavadocCannotBeResolved", u.toExternalForm()));
        }
        return null;
    }

    public List<String> getImportProblems() {
        return importProblems;
    }
    
    private void calculateAbsolutePaths() {
        for (DotClassPathEntry entry : cp.getClassPathEntries()) {
            setAbsolutePathForEntry(entry);
        }
        for (DotClassPathEntry entry : cp.getSourceRoots()) {
            setAbsolutePathForEntry(entry);
        }
        setAbsolutePathForEntry(cp.getOutput());
    }
    
    public DotClassPathEntry getOutput() {
        return cp.getOutput();
    }
    
    /**
     * Inteligently sets absolute path for a given entry with recongnizing of
     * links, projects, variables, relative and absolute entries.
     * If it is not possible (e.g. workspace Varible is not found) sets abs.
     * path to null.
     */
    private void setAbsolutePathForEntry(DotClassPathEntry entry) {
        if (entry == null) {
            return;
        }
        // set abs. path default (null)
        entry.setAbsolutePath(null);
        
        // try to resolve entry as a CONTAINER
        if (entry.getKind() == DotClassPathEntry.Kind.CONTAINER) {
            // we don't support CONTAINERs so we don't care about them here
            // (we support JRE/JDK containers but those are solved elsewhere)
            return;
        }
        
        // try to resolve entry as a VARIABLE
        if (entry.getKind() == DotClassPathEntry.Kind.VARIABLE) {
            String var[] = EclipseUtils.splitVariable(entry.getRawPath());
            Workspace.Variable variable = getVariable(var[0]);
            if (variable != null) {
                entry.setAbsolutePath(variable.getLocation() +var[1]);
            } else {
                logger.warning("cannot resolve variable '"+var[0]+"'. used in project "+ //NOI18N
                        getProjectFile().getPath()+" in entry "+entry); //NOI18N
            }
            return;
        }
        
        // try to resolve entry as a PROJECT
        if (entry.getKind() == DotClassPathEntry.Kind.PROJECT) {
            if (workspace != null) {
                EclipseProject ep = workspace.getProjectByName(entry.getRawPath().substring(1));
                if (ep != null) {
                    entry.setAbsolutePath(ep.getDirectory().getAbsolutePath());
                }
            }
            //            else {
            //                ErrorManager.getDefault().log(ErrorManager.WARNING, "workspace == null");
            //            }
            return;
        }
        
        // not VARIABLE, not PROJECT, not LINK -> either source root or library
        boolean resolved = false;
        String path = entry.getRawPath();
        // first check whether path starts with a project name:
        if (entry.getKind() == DotClassPathEntry.Kind.LIBRARY && workspace != null) {
            String s = resolvePath(path, workspace);
            if (s != null) {
                path = s;
                resolved = true;
            }
        }
        if (!resolved) {
            // convert possibly relative path to absolute:
            if (!Util.isAbsolutePath(path)) {
                path = projectDir.getAbsolutePath()+File.separator+path;
                resolved = true;
            }
        }
        entry.setAbsolutePath(path);
    }
    
    private static String resolvePath(String path, Workspace workspace) {
       File f = new File(path);
        // test whether it is file within a project, e.g. "/some-project/lib/file.jar"
        if (path.startsWith("/") && !f.exists()) { // NOI18N
            String s[] = EclipseUtils.splitProject(path);
            EclipseProject ep = workspace.getProjectByName(s[0]);
            if (ep != null) {
                String projectPath = ep.getDirectory().getAbsolutePath();
                String resolvedPath = resolveLinkPath(s[1], ep.links);
                if (resolvedPath != null) {
                    return resolvedPath;
                }
                return projectPath + s[1];
            }
        }
        return null;
    }
    
    private static String resolveLinkPath(String path, List<Link> links) {
        if (path.startsWith("/") || path.startsWith("\\")) {
            // get rid of first slash
            path = path.substring(1);
        }
        for (Link l : links) {
            if (path.startsWith(l.getName())) {
                return l.getLocation() + path.substring(l.getName().length());
            }
        }
        return null;
    }

    /**
     * Find variable for the given variable rawPath. Note that this method
     * returns <code>null</code> if workspace wasn't set for the project.
     */
    private Workspace.Variable getVariable(String rawPath) {
        if (workspace == null) {
            // workspace wasn't set for this project
            logger.fine("Workspace wasn't set for the project \"" + getName() + "\""); // NOI18N
            return null;
        }
        return workspace.getVariable(rawPath);
    }
    
    @Override
    public String toString() {
        return "EclipseProject[" + getName() + ", " + getDirectory() + "]"; // NOI18N
    }
    
    /* name is enough for now */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof EclipseProject)) return false;
        final EclipseProject ePrj = (EclipseProject) obj;
        if (!name.equals(ePrj.name)) return false;
        return true;
    }
    
    /* name is enough for now */
    @Override
    public int hashCode() {
        int result = 17;
        result = 37 * result + System.identityHashCode(name);
        return result;
    }
    
    /**
     * Compares projects based on theirs <code>name</code>s. Projects which has
     * null-name will be last.
     */
    public int compareTo(Object o) {
        String name1 = getName();
        String name2 = null;
        if (o instanceof EclipseProject) {
            name2 = ((EclipseProject) o).getName();
        }
        if (name2 == null) {
            return (name1 == null ? 0 : -1);
        }
        return (name1 == null ? 1 : name1.compareToIgnoreCase(name2));
    }
}
