/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.ui.internal.console;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IPatternMatchListener;
import org.eclipse.ui.console.PatternMatchEvent;
import org.eclipse.ui.console.TextConsole;

public class ConsolePatternMatcher implements IDocumentListener {

    private MatchJob fMatchJob = new MatchJob();

    /**
     * Collection of compiled pattern match listeners
     */
    private ArrayList patterns = new ArrayList();

    private TextConsole fConsole;

    private boolean fFinalMatch;

	private boolean fScheduleFinal;

    public ConsolePatternMatcher(TextConsole console) {
        fConsole = console;
        fMatchJob.setRule(fConsole.getSchedulingRule());
    }

    private class MatchJob extends Job {
        MatchJob() {
            super("Match Job"); //$NON-NLS-1$
            setSystem(true);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
         */
        protected IStatus run(IProgressMonitor monitor) {
            IDocument doc = fConsole.getDocument();
            String text = null;
            int prevBaseOffset = -1;
            if (doc != null && !monitor.isCanceled()) {
                int endOfSearch = doc.getLength();
                int indexOfLastChar = endOfSearch;
                if (indexOfLastChar > 0) {
                    indexOfLastChar--;
                }
                int lastLineToSearch = 0;
                int offsetOfLastLineToSearch = 0;
                try {
                    lastLineToSearch = doc.getLineOfOffset(indexOfLastChar);
                    offsetOfLastLineToSearch = doc.getLineOffset(lastLineToSearch);
                } catch (BadLocationException e) {
                    // perhaps the buffer was re-set
                    return Status.OK_STATUS;
                }
                for (int i = 0; i < patterns.size(); i++) {
                    if (monitor.isCanceled()) {
                        break;
                    }
                    CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) patterns.get(i);
                    int baseOffset = notifier.end;
                    int lengthToSearch = endOfSearch - baseOffset;
                    if (lengthToSearch > 0) {
                        try {
                            if (prevBaseOffset != baseOffset) {
                                // reuse the text string if possible
                                text = doc.get(baseOffset, lengthToSearch);
                            }
                            Matcher reg = notifier.pattern.matcher(text);
                            Matcher quick = null;
                            if (notifier.qualifier != null) {
                                quick = notifier.qualifier.matcher(text);
                            }
                            int startOfNextSearch = 0;
                            int endOfLastMatch = -1;
                            int lineOfLastMatch = -1;
                            while ((startOfNextSearch < lengthToSearch) && !monitor.isCanceled()) {
                                if (quick != null) {
                                    if (quick.find(startOfNextSearch)) {
                                        // start searching on the beginning
                                        // of the line where the potential
                                        // match was found, or after the
                                        // last match on the same line
                                        int matchLine = doc.getLineOfOffset(baseOffset + quick.start());
                                        if (lineOfLastMatch == matchLine) {
                                            startOfNextSearch = endOfLastMatch;
                                        } else {
                                            startOfNextSearch = doc.getLineOffset(matchLine) - baseOffset;
                                        }
                                    } else {
                                        startOfNextSearch = lengthToSearch;
                                    }
                                }
                                if (startOfNextSearch < 0) {
                                    startOfNextSearch = 0;
                                }
                                if (startOfNextSearch < lengthToSearch) {
                                    if (reg.find(startOfNextSearch)) {
                                        endOfLastMatch = reg.end();
                                        lineOfLastMatch = doc.getLineOfOffset(baseOffset + endOfLastMatch - 1);
                                        int regStart = reg.start();
                                        IPatternMatchListener listener = notifier.listener;
                                        if (listener != null && !monitor.isCanceled()) {
                                            listener.matchFound(new PatternMatchEvent(fConsole, baseOffset + regStart, endOfLastMatch - regStart));
                                        }
                                        startOfNextSearch = endOfLastMatch;
                                    } else {
                                        startOfNextSearch = lengthToSearch;
                                    }
                                }
                            }
                            // update start of next search to the last line
                            // searched
                            // or the end of the last match if it was on the
                            // line that
                            // was last searched
                            if (lastLineToSearch == lineOfLastMatch) {
                                notifier.end = baseOffset + endOfLastMatch;
                            } else {
                                notifier.end = offsetOfLastLineToSearch;
                            }
                        } catch (BadLocationException e) {
                            ConsolePlugin.log(e);
                        }
                    }
                    prevBaseOffset = baseOffset;
                }
            }
            
            if (fFinalMatch) {
                fConsole.matcherFinished();
            } else if (fScheduleFinal) {
            	fFinalMatch = true;
            	schedule();
            }
            

            return Status.OK_STATUS;
        }
    }

    private class CompiledPatternMatchListener {
        Pattern pattern;

        Pattern qualifier;

        IPatternMatchListener listener;

        int end = 0;

        CompiledPatternMatchListener(Pattern pattern, Pattern qualifier, IPatternMatchListener matchListener) {
            this.pattern = pattern;
            this.listener = matchListener;
            this.qualifier = qualifier;
        }

        public void dispose() {
            listener.disconnect();
            pattern = null;
            qualifier = null;
            listener = null;
        }
    }

    /**
     * Adds the given pattern match listener to this console. The listener will
     * be connected and receive match notifications.
     * 
     * @param matchListener
     *            the pattern match listener to add
     */
    public void addPatternMatchListener(IPatternMatchListener matchListener) {
        synchronized (patterns) {
            
            // check for dups
            for (Iterator iter = patterns.iterator(); iter.hasNext();) {
                CompiledPatternMatchListener element = (CompiledPatternMatchListener) iter.next();
                if (element.listener == matchListener) {
                    return;
                }
            }
            
            if (matchListener == null || matchListener.getPattern() == null) {
                throw new IllegalArgumentException("Pattern cannot be null"); //$NON-NLS-1$
            }

            Pattern pattern = Pattern.compile(matchListener.getPattern(), matchListener.getCompilerFlags());
            String qualifier = matchListener.getLineQualifier();
            Pattern qPattern = null;
            if (qualifier != null) {
                qPattern = Pattern.compile(qualifier, matchListener.getCompilerFlags());
            }
            CompiledPatternMatchListener notifier = new CompiledPatternMatchListener(pattern, qPattern, matchListener);
            patterns.add(notifier);
            matchListener.connect(fConsole);
            fMatchJob.schedule();
        }
    }

    /**
     * Removes the given pattern match listener from this console. The listener
     * will be disconnected and will no longer receive match notifications.
     * 
     * @param matchListener
     *            the pattern match listener to remove.
     */
    public void removePatternMatchListener(IPatternMatchListener matchListener) {
        synchronized (patterns) {
            for (Iterator iter = patterns.iterator(); iter.hasNext();) {
                CompiledPatternMatchListener element = (CompiledPatternMatchListener) iter.next();
                if (element.listener == matchListener) {
                    iter.remove();
                    matchListener.disconnect();
                }
            }
        }
    }

    public void disconnect() {
        fMatchJob.cancel();
        synchronized (patterns) {
            Iterator iterator = patterns.iterator();
            while (iterator.hasNext()) {
                CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) iterator.next();
                notifier.dispose();
            }
            patterns.clear();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
     */
    public void documentAboutToBeChanged(DocumentEvent event) {
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
     */
    public void documentChanged(DocumentEvent event) {
        if (event.fLength > 0) {
            synchronized (patterns) {
                if (event.fDocument.getLength() == 0) {
                    // document has been cleared, reset match listeners
                    Iterator iter = patterns.iterator();
                    while (iter.hasNext()) {
                        CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) iter.next();
                        notifier.end = 0;
                    }
                } else {
                    if (event.fOffset == 0) { 
                        //document was trimmed
                        Iterator iter = patterns.iterator();
                        while (iter.hasNext()) {
                            CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) iter.next();
                            notifier.end = notifier.end > event.fLength ? notifier.end-event.fLength : 0;
                        }
                    }
                }
            }
        }
        fMatchJob.schedule();
    }

    /**
     * @return
     */
    public boolean isScheduled() {
        return fMatchJob.getState()==Job.NONE;
    }
    
    public void forceFinalMatching() {
    	fScheduleFinal = true;
    	fMatchJob.schedule();
    }

}
