/*
 *  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.ivyde.eclipse.cp;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import org.apache.ivyde.eclipse.IvyDEException;
import org.apache.ivyde.internal.eclipse.IvyPlugin;
import org.apache.ivyde.internal.eclipse.cpcontainer.IvyClasspathContainerImpl;
import org.apache.ivyde.internal.eclipse.cpcontainer.IvyClasspathUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.ui.packageview.ClassPathContainer;
import org.eclipse.jface.viewers.IStructuredSelection;

public final class IvyClasspathContainerHelper {

    private IvyClasspathContainerHelper() {
        // utility class
    }

    /**
     * Get the Ivy classpath container from the selection in the Java package view
     * 
     * @param selection
     *            the selection
     * @return
     * @throws JavaModelException
     */
    public static IvyClasspathContainer getContainer(IStructuredSelection selection) {
        if (selection == null) {
            return null;
        }
        for (@SuppressWarnings("unchecked")
        Iterator<Object> it = selection.iterator(); it.hasNext();) {
            Object element = it.next();
            IvyClasspathContainerImpl cp = (IvyClasspathContainerImpl) IvyPlugin.adapt(element,
                IvyClasspathContainerImpl.class);
            if (cp != null) {
                return cp;
            }
            if (element instanceof ClassPathContainer) {
                // FIXME: we shouldn't check against internal JDT API but they are not adaptable to
                // useful class
                return IvyClasspathUtil.jdt2IvyCPC((ClassPathContainer) element);
            }
        }
        return null;
    }

    public static boolean isIvyClasspathContainer(IPath containerPath) {
        return containerPath.segment(0).equals(IvyClasspathContainer.ID);
    }

    /**
     * Search the Ivy classpath containers within the specified Java project
     * 
     * @param javaProject
     *            the project to search into
     * @return the Ivy classpath container if found
     */
    public static List<IvyClasspathContainer> getContainers(IJavaProject javaProject) {
        List<IvyClasspathContainer> containers = new ArrayList<IvyClasspathContainer>();
        if (javaProject == null || !javaProject.exists()) {
            return containers;
        }
        try {
            IClasspathEntry[] entries = javaProject.getRawClasspath();
            for (int i = 0; i < entries.length; i++) {
                IClasspathEntry entry = entries[i];
                if (entry != null && entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
                    IPath path = entry.getPath();
                    if (isIvyClasspathContainer(path)) {
                        IClasspathContainer cp = JavaCore.getClasspathContainer(path, javaProject);
                        if (cp instanceof IvyClasspathContainer) {
                            containers.add((IvyClasspathContainer) cp);
                        }
                    }
                }
            }
        } catch (JavaModelException e) {
            // unless there are issues with the JDT, this should never happen
            IvyPlugin.log(e);
        }
        return containers;
    }

    public static List<IvyClasspathContainer> getContainersFromIvyFile(IFile ivyfile) {
        IJavaProject javaProject = JavaCore.create(ivyfile.getProject());
        List<IvyClasspathContainer> containers = new ArrayList<IvyClasspathContainer>();
        if (javaProject == null || !javaProject.exists()) {
            return containers;
        }
        try {
            IClasspathEntry[] entries = javaProject.getRawClasspath();
            for (int i = 0; i < entries.length; i++) {
                IClasspathEntry entry = entries[i];
                if (entry != null && entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
                    IPath path = entry.getPath();
                    if (isIvyClasspathContainer(path)) {
                        IClasspathContainer cp = JavaCore.getClasspathContainer(path, javaProject);
                        if (cp instanceof IvyClasspathContainerImpl) {
                            IvyClasspathContainerImpl ivycp = (IvyClasspathContainerImpl) cp;
                            if (ivycp.getConf().getIvyXmlPath()
                                    .equals(ivyfile.getProjectRelativePath().toString())) {
                                containers.add(ivycp);
                            }
                        }
                    }
                }
            }
        } catch (JavaModelException e) {
            // unless there are issues with the JDT, this should never happen
            IvyPlugin.log(e);
        }
        return containers;
    }

    public static List<IvyClasspathContainer> getContainersFromIvySettings(IFile ivySettings) {
        IJavaProject javaProject = JavaCore.create(ivySettings.getProject());
        List<IvyClasspathContainer> containers = new ArrayList<IvyClasspathContainer>();
        if (javaProject == null || !javaProject.exists()) {
            return containers;
        }
        try {
            IClasspathEntry[] entries = javaProject.getRawClasspath();
            for (int i = 0; i < entries.length; i++) {
                IClasspathEntry entry = entries[i];
                if (entry != null && entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
                    IPath path = entry.getPath();
                    if (isIvyClasspathContainer(path)) {
                        IClasspathContainer cp = JavaCore.getClasspathContainer(path, javaProject);
                        if (cp instanceof IvyClasspathContainerImpl) {
                            IvyClasspathContainerImpl ivycp = (IvyClasspathContainerImpl) cp;
                            ResolvedPath settingsPath;
                            try {
                                settingsPath = ivycp.getConf().getInheritedSettingsSetup()
                                        .getResolvedIvySettingsPath(ivycp.getConf().getProject());
                            } catch (IvyDEException e) {
                                // cannot resolve the ivy settings so just ignore
                                continue;
                            }
                            if (settingsPath.getResolvedPath().equals(
                                ivySettings.getProjectRelativePath().toString())) {
                                containers.add(ivycp);
                            }
                        }
                    }
                }
            }
        } catch (JavaModelException e) {
            // unless there are issues with the JDT, this should never happen
            IvyPlugin.log(e);
        }
        return containers;
    }

    public static IvyClasspathContainer getContainer(IPath containerPath, IJavaProject javaProject) {
        IClasspathContainer cp;
        try {
            cp = JavaCore.getClasspathContainer(containerPath, javaProject);
        } catch (JavaModelException e) {
            IvyPlugin.log(e);
            return null;
        }
        if (!(cp instanceof IvyClasspathContainerImpl)) {
            IvyPlugin.logError("Expected an Ivy container but was " + cp.getClass().getName()
                    + " for path " + containerPath);
            return null;
        }
        return (IvyClasspathContainerImpl) cp;
    }

    /**
     * Search the Ivy classpath entry within the specified Java project with the specific path
     * 
     * @param containerPath
     *            the path of the container
     * @param javaProject
     *            the project to search into
     * @return the Ivy classpath container if found, otherwise return <code>null</code>
     */
    public static IClasspathEntry getEntry(IPath containerPath, IJavaProject javaProject) {
        if (javaProject == null || !javaProject.exists()) {
            return null;
        }
        try {
            IClasspathEntry[] entries = javaProject.getRawClasspath();
            for (int i = 0; i < entries.length; i++) {
                IClasspathEntry entry = entries[i];
                if (entry != null && entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
                    if (containerPath.equals(entry.getPath())) {
                        return entry;
                    }
                }
            }
        } catch (JavaModelException e) {
            // unless there are issues with the JDT, this should never happen
            IvyPlugin.log(e);
        }
        return null;
    }

    public static List<IvyClasspathContainer> getContainers(IProject project) {
        IJavaProject javaProject = JavaCore.create(project);
        if (javaProject != null && javaProject.exists()) {
            return getContainers(javaProject);
        }
        return Collections.emptyList();
    }

    /**
     * This will return all ivy projects in the workspace <br>
     * 
     * @return collection of ivy projects
     */
    public static IProject[] getIvyProjectsInWorkspace() {
        Collection<IProject> ivyProjects = new HashSet<IProject>();

        IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();

        for (int i = 0; i < projects.length; i++) {
            if (projects[i].isOpen() && getContainers(projects[i]).size() > 0) {
                ivyProjects.add(projects[i]);
            }
        }

        return (IProject[]) ivyProjects.toArray(new IProject[ivyProjects.size()]);
    }

}
