/*
 * Copyright (C) 2011 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.editors.layout.gre;

import com.android.ide.common.api.IViewRule;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.sdklib.internal.project.ProjectProperties;
import com.android.utils.Pair;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.QualifiedName;

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

/**
 * The {@link RuleLoader} is responsible for loading (and unloading)
 * {@link IViewRule} classes. There is typically one {@link RuleLoader}
 * per project.
 */
public class RuleLoader {
    /**
     * Qualified name for the per-project non-persistent property storing the
     * {@link RuleLoader} for this project
     */
    private final static QualifiedName RULE_LOADER = new QualifiedName(AdtPlugin.PLUGIN_ID,
            "ruleloader"); //$NON-NLS-1$

    private final IProject mProject;
    private ClassLoader mUserClassLoader;
    private List<Pair<File, Long>> mUserJarTimeStamps;
    private long mLastCheckTimeStamp;

    /**
     * Flag set when we've attempted to initialize the {@link #mUserClassLoader}
     * already
     */
    private boolean mUserClassLoaderInited;

    /**
     * Returns the {@link RuleLoader} for the given project
     *
     * @param project the project the loader is associated with
     * @return an {@RuleLoader} for the given project,
     *         never null
     */
    public static RuleLoader get(IProject project) {
        RuleLoader loader = null;
        try {
            loader = (RuleLoader) project.getSessionProperty(RULE_LOADER);
        } catch (CoreException e) {
            // Not a problem; we will just create a new one
        }
        if (loader == null) {
            loader = new RuleLoader(project);
            try {
                project.setSessionProperty(RULE_LOADER, loader);
            } catch (CoreException e) {
                AdtPlugin.log(e, "Can't store RuleLoader");
            }
        }
        return loader;
    }

    /** Do not call; use the {@link #get} factory method instead. */
    private RuleLoader(IProject project) {
        mProject = project;
    }

    /**
     * Find out whether the given project has 3rd party ViewRules, and if so
     * return a ClassLoader which can locate them. If not, return null.
     * @param project The project to load user rules from
     * @return A class loader which can user view rules, or otherwise null
     */
    private ClassLoader computeUserClassLoader(IProject project) {
        // Default place to locate layout rules. The user may also add to this
        // path by defining a config property specifying
        // additional .jar files to search via a the layoutrules.jars property.
        ProjectState state = Sdk.getProjectState(project);
        ProjectProperties projectProperties = state.getProperties();

        // Ensure we have the latest & greatest version of the properties.
        // This allows users to reopen editors in a running Eclipse instance
        // to get updated view rule jars
        projectProperties.reload();

        String path = projectProperties.getProperty(
                ProjectProperties.PROPERTY_RULES_PATH);

        if (path != null && path.length() > 0) {

            mUserJarTimeStamps = new ArrayList<Pair<File, Long>>();
            mLastCheckTimeStamp = System.currentTimeMillis();

            List<URL> urls = new ArrayList<URL>();
            String[] pathElements = path.split(File.pathSeparator);
            for (String pathElement : pathElements) {
                pathElement = pathElement.trim(); // Avoid problems with trailing whitespace etc
                File pathFile = new File(pathElement);
                if (!pathFile.isAbsolute()) {
                    pathFile = new File(project.getLocation().toFile(), pathElement);
                }
                // Directories and jar files are okay. Do we need to
                // validate the files here as .jar files?
                if (pathFile.isFile() || pathFile.isDirectory()) {
                    URL url;
                    try {
                        url = pathFile.toURI().toURL();
                        urls.add(url);

                        mUserJarTimeStamps.add(Pair.of(pathFile, pathFile.lastModified()));
                    } catch (MalformedURLException e) {
                        AdtPlugin.log(IStatus.WARNING,
                                "Invalid URL: %1$s", //$NON-NLS-1$
                                e.toString());
                    }
                }
            }

            if (urls.size() > 0) {
                return new URLClassLoader(urls.toArray(new URL[urls.size()]),
                        RulesEngine.class.getClassLoader());
            }
        }

        return null;
    }

    /**
     * Return the class loader to use for custom views, or null if no custom
     * view rules are registered for the project. Note that this class loader
     * can change over time (if the jar files are updated), so callers should be
     * prepared to unload previous instances.
     *
     * @return a class loader to use for custom view rules, or null
     */
    public ClassLoader getClassLoader() {
        if (mUserClassLoader == null) {
            // Only attempt to load rule paths once.
            // TODO: Check the timestamp on the project.properties file so we can dynamically
            // pick up cases where the user edits the path
            if (!mUserClassLoaderInited) {
                mUserClassLoaderInited = true;
                mUserClassLoader = computeUserClassLoader(mProject);
            }
        } else {
            // Check the timestamp on the jar files in the custom view path to see if we
            // need to reload the classes (but only do this at most every 3 seconds)
            if (mUserJarTimeStamps != null) {
                long time = System.currentTimeMillis();
                if (time - mLastCheckTimeStamp > 3000) {
                    mLastCheckTimeStamp = time;
                    for (Pair<File, Long> pair : mUserJarTimeStamps) {
                        File file = pair.getFirst();
                        Long prevModified = pair.getSecond();
                        long modified = file.lastModified();
                        if (prevModified.longValue() != modified) {
                            mUserClassLoaderInited = true;
                            mUserJarTimeStamps = null;
                            mUserClassLoader = computeUserClassLoader(mProject);
                        }
                    }
                }
            }
        }

        return mUserClassLoader;
    }
}
