/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
 *
 * 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 com.android.ide.eclipse.adt.internal.resources.manager;

import com.android.SdkConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.build.BuildHelper;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
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.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

/**
 * ClassLoader able to load class from output of an Eclipse project.
 */
public final class ProjectClassLoader extends ClassLoader {

    private final IJavaProject mJavaProject;
    private URLClassLoader mJarClassLoader;
    private boolean mInsideJarClassLoader = false;

    public ProjectClassLoader(ClassLoader parentClassLoader, IProject project) {
        super(parentClassLoader);
        mJavaProject = JavaCore.create(project);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // if we are here through a child classloader, throw an exception.
        if (mInsideJarClassLoader) {
            throw new ClassNotFoundException(name);
        }

        // attempt to load the class from the main project
        Class<?> clazz = loadFromProject(mJavaProject, name);

        if (clazz != null) {
            return clazz;
        }

        // attempt to load the class from the jar dependencies
        clazz = loadClassFromJar(name);
        if (clazz != null) {
            return clazz;
        }

        // attempt to load the class from the libraries
        try {
            // get the project info
            ProjectState projectState = Sdk.getProjectState(mJavaProject.getProject());

            // this can happen if the project has no project.properties.
            if (projectState != null) {

                List<IProject> libProjects = projectState.getFullLibraryProjects();
                List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(
                        libProjects);

                for (IJavaProject javaProject : referencedJavaProjects) {
                    clazz = loadFromProject(javaProject, name);

                    if (clazz != null) {
                        return clazz;
                    }
                }
            }
        } catch (CoreException e) {
            // log exception?
        }

        throw new ClassNotFoundException(name);
    }

    /**
     * Attempts to load a class from a project output folder.
     * @param project the project to load the class from
     * @param name the name of the class
     * @return a class object if found, null otherwise.
     */
    private Class<?> loadFromProject(IJavaProject project, String name) {
        try {
            // get the project output folder.
            IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
            IPath outputLocation = project.getOutputLocation();
            IResource outRes = root.findMember(outputLocation);
            if (outRes == null) {
                return null;
            }

            File outFolder = new File(outRes.getLocation().toOSString());

            // get the class name segments
            String[] segments = name.split("\\."); //$NON-NLS-1$

            // try to load the class from the bin folder of the project.
            File classFile = getFile(outFolder, segments, 0);
            if (classFile == null) {
                return null;
            }

            // load the content of the file and create the class.
            FileInputStream fis = new FileInputStream(classFile);
            byte[] data = new byte[(int)classFile.length()];
            int read = 0;
            try {
                read = fis.read(data);
            } catch (IOException e) {
                data = null;
            }
            fis.close();

            if (data != null) {
                try {
                    Class<?> clazz = defineClass(null, data, 0, read);
                    if (clazz != null) {
                        return clazz;
                    }
                } catch (UnsupportedClassVersionError e) {
                    // Attempt to reload on lower version
                    int maxVersion = 50; // JDK 1.6
                    try {
                        byte[] rewritten = rewriteClass(data, maxVersion, 0);
                        return defineClass(null, rewritten, 0, rewritten.length);
                    } catch (UnsupportedClassVersionError e2) {
                        throw e; // throw *original* exception, not attempt to rewrite
                    }
                }
            }
        } catch (Exception e) {
            // log the exception?
        }

        return null;
    }

    /**
     * Rewrites the given class to the given target class file version.
     */
    public static byte[] rewriteClass(byte[] classData, final int maxVersion, final int minVersion) {
        assert maxVersion >= minVersion;
        ClassWriter classWriter = new ClassWriter(0);
        ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5, classWriter) {
            @Override
            public void visit(int version, int access, String name, String signature,
                    String superName, String[] interfaces) {
                if (version > maxVersion) {
                    version = maxVersion;
                }
                if (version < minVersion) {
                    version = minVersion;
                }
                super.visit(version, access, name, signature, superName, interfaces);
            }
        };
        ClassReader reader = new ClassReader(classData);
        reader.accept(classVisitor, 0);
        return classWriter.toByteArray();
    }

    /**
     * Returns the File matching the a certain path from a root {@link File}.
     * <p/>The methods checks that the file ends in .class even though the last segment
     * does not.
     * @param parent the root of the file.
     * @param segments the segments containing the path of the file
     * @param index the offset at which to start looking into segments.
     * @throws FileNotFoundException
     */
    private File getFile(File parent, String[] segments, int index)
            throws FileNotFoundException {
        // reached the end with no match?
        if (index == segments.length) {
            throw new FileNotFoundException();
        }

        String toMatch = segments[index];
        File[] files = parent.listFiles();

        // we're at the last segments. we look for a matching <file>.class
        if (index == segments.length - 1) {
            toMatch = toMatch + ".class";

            if (files != null) {
                for (File file : files) {
                    if (file.isFile() && file.getName().equals(toMatch)) {
                        return file;
                    }
                }
            }

            // no match? abort.
            throw new FileNotFoundException();
        }

        String innerClassName = null;

        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    if (toMatch.equals(file.getName())) {
                        return getFile(file, segments, index+1);
                    }
                } else if (file.getName().startsWith(toMatch)) {
                    if (innerClassName == null) {
                        StringBuilder sb = new StringBuilder(segments[index]);
                        for (int i = index + 1 ; i < segments.length ; i++) {
                            sb.append('$');
                            sb.append(segments[i]);
                        }
                        sb.append(".class");

                        innerClassName = sb.toString();
                    }

                    if (file.getName().equals(innerClassName)) {
                        return file;
                    }
                }
            }
        }

        return null;
    }

    /**
     * Loads a class from the 3rd party jar present in the project
     *
     * @return the class loader or null if not found.
     */
    private Class<?> loadClassFromJar(String name) {
        if (mJarClassLoader == null) {
            // get the OS path to all the external jars
            URL[] jars = getExternalJars();

            mJarClassLoader = new URLClassLoader(jars, this /* parent */);
        }

        try {
            // because a class loader always look in its parent loader first, we need to know
            // that we are querying the jar classloader. This will let us know to not query
            // it again for classes we don't find, or this would create an infinite loop.
            mInsideJarClassLoader = true;
            return mJarClassLoader.loadClass(name);
        } catch (ClassNotFoundException e) {
            // not found? return null.
            return null;
        } finally {
            mInsideJarClassLoader = false;
        }
    }

    /**
     * Returns an array of external jar files used by the project.
     * @return an array of OS-specific absolute file paths
     */
    private final URL[] getExternalJars() {
        // get a java project from it
        IJavaProject javaProject = JavaCore.create(mJavaProject.getProject());

        ArrayList<URL> oslibraryList = new ArrayList<URL>();
        IClasspathEntry[] classpaths = javaProject.readRawClasspath();
        if (classpaths != null) {
            for (IClasspathEntry e : classpaths) {
                if (e.getEntryKind() == IClasspathEntry.CPE_LIBRARY ||
                        e.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
                    // if this is a classpath variable reference, we resolve it.
                    if (e.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
                        e = JavaCore.getResolvedClasspathEntry(e);
                    }

                    handleClassPathEntry(e, oslibraryList);
                } else if (e.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
                    // get the container.
                    try {
                        IClasspathContainer container = JavaCore.getClasspathContainer(
                                e.getPath(), javaProject);
                        // ignore the system and default_system types as they represent
                        // libraries that are part of the runtime.
                        if (container != null &&
                                container.getKind() == IClasspathContainer.K_APPLICATION) {
                            IClasspathEntry[] entries = container.getClasspathEntries();
                            for (IClasspathEntry entry : entries) {
                                // TODO: Xav -- is this necessary?
                                if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
                                    entry = JavaCore.getResolvedClasspathEntry(entry);
                                }

                                handleClassPathEntry(entry, oslibraryList);
                            }
                        }
                    } catch (JavaModelException jme) {
                        // can't resolve the container? ignore it.
                        AdtPlugin.log(jme, "Failed to resolve ClasspathContainer: %s",
                                e.getPath());
                    }
                }
            }
        }

        return oslibraryList.toArray(new URL[oslibraryList.size()]);
    }

    private void handleClassPathEntry(IClasspathEntry e, ArrayList<URL> oslibraryList) {
        // get the IPath
        IPath path = e.getPath();

        // check the name ends with .jar
        if (SdkConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
            boolean local = false;
            IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
            if (resource != null && resource.exists() &&
                    resource.getType() == IResource.FILE) {
                local = true;
                try {
                    oslibraryList.add(new File(resource.getLocation().toOSString())
                            .toURI().toURL());
                } catch (MalformedURLException mue) {
                    // pass
                }
            }

            if (local == false) {
                // if the jar path doesn't match a workspace resource,
                // then we get an OSString and check if this links to a valid file.
                String osFullPath = path.toOSString();

                File f = new File(osFullPath);
                if (f.exists()) {
                    try {
                        oslibraryList.add(f.toURI().toURL());
                    } catch (MalformedURLException mue) {
                        // pass
                    }
                }
            }
        }
    }
}
