/*
 * Copyright (C) 2007 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.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.resources.ResourceFile;
import com.android.ide.common.resources.ResourceFolder;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;

import java.util.ArrayList;

/**
 * The Global Project Monitor tracks project file changes, and forward them to simple project,
 * file, and folder listeners.
 * Those listeners can be setup with masks to listen to particular events.
 * <p/>
 * To track project resource changes, use the monitor in the {@link ResourceManager}. It is more
 * efficient and while the global ProjectMonitor can track any file, deleted resource files
 * cannot be matched to previous {@link ResourceFile} or {@link ResourceFolder} objects by the
 * time the listeners get the event notifications.
 *
 * @see IProjectListener
 * @see IFolderListener
 * @see IFileListener
 */
public final class GlobalProjectMonitor {

    private final static GlobalProjectMonitor sThis = new GlobalProjectMonitor();

    /**
     * Classes which implement this interface provide a method that deals
     * with file change events.
     */
    public interface IFileListener {
        /**
         * Sent when a file changed.
         *
         * @param file The file that changed.
         * @param markerDeltas The marker deltas for the file.
         * @param kind The change kind. This is equivalent to
         *            {@link IResourceDelta#accept(IResourceDeltaVisitor)}
         * @param extension the extension of the file or null if the file does
         *            not have an extension
         * @param flags the {@link IResourceDelta#getFlags()} value with details
         *            on what changed in the file
         * @param isAndroidProject whether the parent project is an Android Project
         */
        public void fileChanged(@NonNull IFile file, @NonNull IMarkerDelta[] markerDeltas,
                int kind, @Nullable String extension, int flags, boolean isAndroidProject);
    }

    /**
     * Classes which implements this interface provide methods dealing with project events.
     */
    public interface IProjectListener {
        /**
         * Sent for each opened android project at the time the listener is put in place.
         * @param project the opened project.
         */
        public void projectOpenedWithWorkspace(IProject project);

        /**
         * Sent once after all Android projects have been opened,
         * at the time the listener is put in place.
         * <p/>
         * This is called after {@link #projectOpenedWithWorkspace(IProject)} has
         * been called on all known Android projects.
         */
        public void allProjectsOpenedWithWorkspace();

        /**
         * Sent when a project is opened.
         * @param project the project being opened.
         */
        public void projectOpened(IProject project);

        /**
         * Sent when a project is closed.
         * @param project the project being closed.
         */
        public void projectClosed(IProject project);

        /**
         * Sent when a project is deleted.
         * @param project the project about to be deleted.
         */
        public void projectDeleted(IProject project);

        /**
         * Sent when a project is renamed. During a project rename
         * {@link #projectDeleted(IProject)} and {@link #projectOpened(IProject)} are also called.
         * This is called last.
         *
         * @param project the new {@link IProject} object.
         * @param from the path of the project before the rename action.
         */
        public void projectRenamed(IProject project, IPath from);
    }

    /**
     * Classes which implement this interface provide a method that deals
     * with folder change events
     */
    public interface IFolderListener {
        /**
         * Sent when a folder changed.
         * @param folder The file that was changed
         * @param kind The change kind. This is equivalent to {@link IResourceDelta#getKind()}
         * @param isAndroidProject whether the parent project is an Android Project
         */
        public void folderChanged(IFolder folder, int kind, boolean isAndroidProject);
    }

    /**
     * Interface for a listener to be notified when resource change event starts and ends.
     */
    public interface IResourceEventListener {
        public void resourceChangeEventStart();
        public void resourceChangeEventEnd();
    }

    /**
     * Interface for a listener that gets passed the raw delta without processing.
     */
    public interface IRawDeltaListener {
        public void visitDelta(IResourceDelta delta);
    }

    /**
     * Base listener bundle to associate a listener to an event mask.
     */
    private static class ListenerBundle {
        /** Mask value to accept all events */
        public final static int MASK_NONE = -1;

        /**
         * Event mask. Values accepted are IResourceDelta.###
         * @see IResourceDelta#ADDED
         * @see IResourceDelta#REMOVED
         * @see IResourceDelta#CHANGED
         * @see IResourceDelta#ADDED_PHANTOM
         * @see IResourceDelta#REMOVED_PHANTOM
         * */
        int kindMask;
    }

    /**
     * Listener bundle for file event.
     */
    private static class FileListenerBundle extends ListenerBundle {

        /** The file listener */
        IFileListener listener;
    }

    /**
     * Listener bundle for folder event.
     */
    private static class FolderListenerBundle extends ListenerBundle {
        /** The file listener */
        IFolderListener listener;
    }

    private final ArrayList<FileListenerBundle> mFileListeners =
        new ArrayList<FileListenerBundle>();

    private final ArrayList<FolderListenerBundle> mFolderListeners =
        new ArrayList<FolderListenerBundle>();

    private final ArrayList<IProjectListener> mProjectListeners = new ArrayList<IProjectListener>();

    private final ArrayList<IResourceEventListener> mEventListeners =
        new ArrayList<IResourceEventListener>();

    private final ArrayList<IRawDeltaListener> mRawDeltaListeners =
        new ArrayList<IRawDeltaListener>();

    private IWorkspace mWorkspace;

    private boolean mIsAndroidProject;

    /**
     * Delta visitor for resource changes.
     */
    private final class DeltaVisitor implements IResourceDeltaVisitor {

        @Override
        public boolean visit(IResourceDelta delta) {
            // Find the other resource listeners to notify
            IResource r = delta.getResource();
            int type = r.getType();
            if (type == IResource.FILE) {
                int kind = delta.getKind();
                // notify the listeners.
                for (FileListenerBundle bundle : mFileListeners) {
                    if (bundle.kindMask == ListenerBundle.MASK_NONE
                            || (bundle.kindMask & kind) != 0) {
                        try {
                            bundle.listener.fileChanged((IFile)r, delta.getMarkerDeltas(), kind,
                                    r.getFileExtension(), delta.getFlags(), mIsAndroidProject);
                        } catch (Throwable t) {
                            AdtPlugin.log(t,"Failed to call IFileListener.fileChanged");
                        }
                    }
                }
                return false;
            } else if (type == IResource.FOLDER) {
                int kind = delta.getKind();
                // notify the listeners.
                for (FolderListenerBundle bundle : mFolderListeners) {
                    if (bundle.kindMask == ListenerBundle.MASK_NONE
                            || (bundle.kindMask & kind) != 0) {
                        try {
                            bundle.listener.folderChanged((IFolder)r, kind, mIsAndroidProject);
                        } catch (Throwable t) {
                            AdtPlugin.log(t,"Failed to call IFileListener.folderChanged");
                        }
                    }
                }
                return true;
            } else if (type == IResource.PROJECT) {
                IProject project = (IProject)r;

                try {
                    mIsAndroidProject = project.hasNature(AdtConstants.NATURE_DEFAULT);
                } catch (CoreException e) {
                    // this can only happen if the project does not exist or is not open, neither
                    // of which can happen here since we are processing changes in the project
                    // or at worst a project post-open event.
                    return false;
                }

                if (mIsAndroidProject == false) {
                    // for non android project, skip the project listeners but return true
                    // to visit the children and notify the IFileListeners
                    return true;
                }

                int flags = delta.getFlags();

                if ((flags & IResourceDelta.OPEN) != 0) {
                    // the project is opening or closing.

                    if (project.isOpen()) {
                        // notify the listeners.
                        for (IProjectListener pl : mProjectListeners) {
                            try {
                                pl.projectOpened(project);
                            } catch (Throwable t) {
                                AdtPlugin.log(t,"Failed to call IProjectListener.projectOpened");
                            }
                        }
                    } else {
                        // notify the listeners.
                        for (IProjectListener pl : mProjectListeners) {
                            try {
                                pl.projectClosed(project);
                            } catch (Throwable t) {
                                AdtPlugin.log(t,"Failed to call IProjectListener.projectClosed");
                            }
                        }
                    }

                    if ((flags & IResourceDelta.MOVED_FROM) != 0) {
                        IPath from = delta.getMovedFromPath();
                        // notify the listeners.
                        for (IProjectListener pl : mProjectListeners) {
                            try {
                                pl.projectRenamed(project, from);
                            } catch (Throwable t) {
                                AdtPlugin.log(t,"Failed to call IProjectListener.projectRenamed");
                            }
                        }
                    }
                }
            }

            return true;
        }
    }

    public static GlobalProjectMonitor getMonitor() {
        return sThis;
    }


    /**
     * Starts the resource monitoring.
     * @param ws The current workspace.
     * @return The monitor object.
     */
    public static GlobalProjectMonitor startMonitoring(IWorkspace ws) {
        if (sThis != null) {
            ws.addResourceChangeListener(sThis.mResourceChangeListener,
                    IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_DELETE);
            sThis.mWorkspace = ws;
        }
        return sThis;
    }

    /**
     * Stops the resource monitoring.
     * @param ws The current workspace.
     */
    public static void stopMonitoring(IWorkspace ws) {
        if (sThis != null) {
            ws.removeResourceChangeListener(sThis.mResourceChangeListener);

            synchronized (sThis) {
                sThis.mFileListeners.clear();
                sThis.mProjectListeners.clear();
            }
        }
    }

    /**
     * Adds a file listener.
     * @param listener The listener to receive the events.
     * @param kindMask The event mask to filter out specific events.
     * {@link ListenerBundle#MASK_NONE} will forward all events.
     * See {@link ListenerBundle#kindMask} for more values.
     */
    public synchronized void addFileListener(IFileListener listener, int kindMask) {
        FileListenerBundle bundle = new FileListenerBundle();
        bundle.listener = listener;
        bundle.kindMask = kindMask;

        mFileListeners.add(bundle);
    }

    /**
     * Removes an existing file listener.
     * @param listener the listener to remove.
     */
    public synchronized void removeFileListener(IFileListener listener) {
        for (int i = 0 ; i < mFileListeners.size() ; i++) {
            FileListenerBundle bundle = mFileListeners.get(i);
            if (bundle.listener == listener) {
                mFileListeners.remove(i);
                return;
            }
        }
    }

    /**
     * Adds a folder listener.
     * @param listener The listener to receive the events.
     * @param kindMask The event mask to filter out specific events.
     * {@link ListenerBundle#MASK_NONE} will forward all events.
     * See {@link ListenerBundle#kindMask} for more values.
     */
    public synchronized void addFolderListener(IFolderListener listener, int kindMask) {
        FolderListenerBundle bundle = new FolderListenerBundle();
        bundle.listener = listener;
        bundle.kindMask = kindMask;

        mFolderListeners.add(bundle);
    }

    /**
     * Removes an existing folder listener.
     * @param listener the listener to remove.
     */
    public synchronized void removeFolderListener(IFolderListener listener) {
        for (int i = 0 ; i < mFolderListeners.size() ; i++) {
            FolderListenerBundle bundle = mFolderListeners.get(i);
            if (bundle.listener == listener) {
                mFolderListeners.remove(i);
                return;
            }
        }
    }

    /**
     * Adds a project listener.
     * @param listener The listener to receive the events.
     */
    public synchronized void addProjectListener(IProjectListener listener) {
        mProjectListeners.add(listener);

        // we need to look at the opened projects and give them to the listener.

        // get the list of opened android projects.
        IWorkspaceRoot workspaceRoot = mWorkspace.getRoot();
        IJavaModel javaModel = JavaCore.create(workspaceRoot);
        IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects(javaModel,
                null /*filter*/);


        notifyResourceEventStart();

        for (IJavaProject androidProject : androidProjects) {
            listener.projectOpenedWithWorkspace(androidProject.getProject());
        }

        listener.allProjectsOpenedWithWorkspace();

        notifyResourceEventEnd();
    }

    /**
     * Removes an existing project listener.
     * @param listener the listener to remove.
     */
    public synchronized void removeProjectListener(IProjectListener listener) {
        mProjectListeners.remove(listener);
    }

    /**
     * Adds a resource event listener.
     * @param listener The listener to receive the events.
     */
    public synchronized void addResourceEventListener(IResourceEventListener listener) {
        mEventListeners.add(listener);
    }

    /**
     * Removes an existing Resource Event listener.
     * @param listener the listener to remove.
     */
    public synchronized void removeResourceEventListener(IResourceEventListener listener) {
        mEventListeners.remove(listener);
    }

    /**
     * Adds a raw delta listener.
     * @param listener The listener to receive the deltas.
     */
    public synchronized void addRawDeltaListener(IRawDeltaListener listener) {
        mRawDeltaListeners.add(listener);
    }

    /**
     * Removes an existing Raw Delta listener.
     * @param listener the listener to remove.
     */
    public synchronized void removeRawDeltaListener(IRawDeltaListener listener) {
        mRawDeltaListeners.remove(listener);
    }

    private void notifyResourceEventStart() {
        for (IResourceEventListener listener : mEventListeners) {
            try {
                listener.resourceChangeEventStart();
            } catch (Throwable t) {
                AdtPlugin.log(t,"Failed to call IResourceEventListener.resourceChangeEventStart");
            }
        }
    }

    private void notifyResourceEventEnd() {
        for (IResourceEventListener listener : mEventListeners) {
            try {
                listener.resourceChangeEventEnd();
            } catch (Throwable t) {
                AdtPlugin.log(t,"Failed to call IResourceEventListener.resourceChangeEventEnd");
            }
        }
    }

    private IResourceChangeListener mResourceChangeListener = new IResourceChangeListener() {
        /**
         * Processes the workspace resource change events.
         *
         * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent)
         */
        @Override
        public synchronized void resourceChanged(IResourceChangeEvent event) {
            // notify the event listeners of a start.
            notifyResourceEventStart();

            if (event.getType() == IResourceChangeEvent.PRE_DELETE) {
                // a project is being deleted. Lets get the project object and remove
                // its compiled resource list.
                IResource r = event.getResource();
                IProject project = r.getProject();

                // notify the listeners.
                for (IProjectListener pl : mProjectListeners) {
                    try {
                        if (project.hasNature(AdtConstants.NATURE_DEFAULT)) {
                            try {
                                pl.projectDeleted(project);
                            } catch (Throwable t) {
                                AdtPlugin.log(t,"Failed to call IProjectListener.projectDeleted");
                            }
                        }
                    } catch (CoreException e) {
                        // just ignore this project.
                    }
                }
            } else {
                // this a regular resource change. We get the delta and go through it with a visitor.
                IResourceDelta delta = event.getDelta();

                // notify the raw delta listeners
                for (IRawDeltaListener listener : mRawDeltaListeners) {
                    listener.visitDelta(delta);
                }

                DeltaVisitor visitor = new DeltaVisitor();
                try {
                    delta.accept(visitor);
                } catch (CoreException e) {
                }
            }

            // we're done, notify the event listeners.
            notifyResourceEventEnd();
        }
    };
}
