/**
 * 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.netbeans.lib.editor.codetemplates;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import java.util.prefs.Preferences;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.Caret;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.Position;
import javax.swing.undo.UndoableEdit;
import org.netbeans.api.editor.mimelookup.MimeLookup;
import org.netbeans.api.editor.mimelookup.MimePath;
import org.netbeans.editor.Acceptor;
import org.netbeans.editor.AcceptorFactory;
import org.netbeans.lib.editor.codetemplates.api.CodeTemplate;
import org.netbeans.lib.editor.codetemplates.spi.CodeTemplateFilter;
import org.netbeans.lib.editor.util.swing.DocumentUtilities;
import org.netbeans.spi.editor.hints.ErrorDescription;
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
import org.netbeans.spi.editor.hints.Fix;
import org.netbeans.spi.editor.hints.HintsController;
import org.netbeans.spi.editor.hints.Severity;
import org.openide.ErrorManager;
import org.openide.text.CloneableEditorSupport;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.WeakListeners;


/**
 * Abbreviation detection detects typing of an abbreviation
 * in the document.
 *
 * @author Miloslav Metelka
 * @version 1.00
 */

public final class AbbrevDetection implements DocumentListener, PropertyChangeListener, KeyListener, CaretListener, PreferenceChangeListener {

    private static final Logger LOG = Logger.getLogger(AbbrevDetection.class.getName());
    private static final RequestProcessor RP = new RequestProcessor(AbbrevDetection.class.getName());
    
    /**
     * Document property which determines whether an ongoing document modification
     * should be completely ignored by the abbreviation framework.
     * <br/>
     * This is useful e.g. for code templates parameter replication.
     */
    private static final String ABBREV_IGNORE_MODIFICATION_DOC_PROPERTY
            = "abbrev-ignore-modification"; // NOI18N

    private static final String EDITING_TEMPLATE_DOC_PROPERTY = "code-template-insert-handler"; //NOI18N

    private static final String SURROUND_WITH = NbBundle.getMessage(SurroundWithFix.class, "TXT_SurroundWithHint_Label"); //NOI18N
    private static final int SURROUND_WITH_DELAY = 250;
    
    public static AbbrevDetection get(JTextComponent component) {
        AbbrevDetection ad = (AbbrevDetection)component.getClientProperty(AbbrevDetection.class);
        if (ad == null) {
            ad = new AbbrevDetection(component);
            component.putClientProperty(AbbrevDetection.class, ad);
        }
        return ad;
    }
    
    public static synchronized void remove(JTextComponent component) {
        AbbrevDetection ad = (AbbrevDetection)component.getClientProperty(AbbrevDetection.class);
        if (ad != null) {
            assert ad.component == component : "Wrong component: AbbrevDetection.component=" + ad.component + ", component=" + component;
            ad.uninstall();
            component.putClientProperty(AbbrevDetection.class, null);
        }
    }
    
    private JTextComponent component;
    
    /** Document for which this abbreviation detection was constructed. */
    private Document doc;
    private DocumentListener weakDocL;
    
    /**
     * Offset after the last typed character of the collected abbreviation.
     */
    private Position abbrevEndPosition;

    /**
     * Abbreviation characters captured from typing.
     */
    private final StringBuffer abbrevChars = new StringBuffer();

//    /** Chars on which to expand acceptor */
//    private Acceptor expandAcceptor;

    /** Which chars reset abbreviation accounting */
    private Acceptor resetAcceptor;
    
    private MimePath mimePath = null;
    private Preferences prefs = null;
    private PreferenceChangeListener weakPrefsListener = null;
    
    private ErrorDescription errorDescription = null;
    private List<Fix> surrounsWithFixes = null;
    private Timer surroundsWithTimer;
    
    private AbbrevDetection(JTextComponent component) {
        this.component = component;
        component.addCaretListener(this);
        doc = component.getDocument();
        if (doc != null) {
            listenOnDoc();
        }

        String mimeType = DocumentUtilities.getMimeType(component);
        if (mimeType != null) {
            mimePath = MimePath.parse(mimeType);
            prefs = MimeLookup.getLookup(mimePath).lookup(Preferences.class);
            prefs.addPreferenceChangeListener(WeakListeners.create(PreferenceChangeListener.class, this, prefs));
        }
        
        // Load the settings
        preferenceChange(null);
        
        component.addKeyListener(this);
        component.addPropertyChangeListener(this);
        
        surroundsWithTimer = new Timer(0, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // #124515, give up when the document is locked otherwise we are likely
                // to cause a deadlock.
                if (!DocumentUtilities.isReadLocked(doc)) {
                    showSurroundWithHint();
                }
            }
        });
        surroundsWithTimer.setRepeats(false);
    }
    
    private void listenOnDoc() {
        weakDocL = WeakListeners.document(this, doc);
        doc.addDocumentListener(weakDocL);
    }

    private void uninstall() {
        assert component != null : "Can't call uninstall before the construction finished";
        component.removeCaretListener(this);
        if (doc != null) {
            listenOnDoc();
        }

        component.removeKeyListener(this);
        component.removePropertyChangeListener(this);
        surroundsWithTimer.stop();
    }
    
    public void preferenceChange(PreferenceChangeEvent evt) {
        String settingName = evt == null ? null : evt.getKey();
        if (settingName == null || "abbrev-reset-acceptor".equals(settingName)) { //NOI18N
            resetAcceptor = getResetAcceptor(prefs, mimePath);
        }
    }
    
    public void insertUpdate(DocumentEvent evt) {
        if (!isIgnoreModification()) {
            if (DocumentUtilities.isTypingModification(evt.getDocument()) && !isAbbrevDisabled()) {
                int offset = evt.getOffset();
                int length = evt.getLength();
                appendTypedText(offset, length);
            } else { // not typing modification -> reset abbreviation collecting
                resetAbbrevChars();
            }
        }
    }

    public void removeUpdate(DocumentEvent evt) {
        if (!isIgnoreModification()) {
            if (DocumentUtilities.isTypingModification(evt.getDocument()) && !isAbbrevDisabled()) {
                int offset = evt.getOffset();
                int length = evt.getLength();
                removeAbbrevText(offset, length);
            } else { // not typing modification -> reset abbreviation collecting
                resetAbbrevChars();
            }
        }
    }

    public void changedUpdate(DocumentEvent evt) {
    }

    public void propertyChange(PropertyChangeEvent evt) {
        if ("document".equals(evt.getPropertyName())) { //NOI18N
            if (doc != null && weakDocL != null) {
                doc.removeDocumentListener(weakDocL);
                weakDocL = null;
            }
            
            doc = component.getDocument();
            if (doc != null) {
                listenOnDoc();
            }

            // unregister and destroy the old preferences (if we have any)
            if (prefs != null) {
                prefs.removePreferenceChangeListener(weakPrefsListener);
                prefs = null;
                weakPrefsListener = null;
                mimePath = null;
            }
            
            // load and hook up to preferences for the new mime type
            String mimeType = DocumentUtilities.getMimeType(component);
            if (mimeType != null) {
                mimePath = MimePath.parse(mimeType);
                prefs = MimeLookup.getLookup(mimePath).lookup(Preferences.class);
                weakPrefsListener = WeakListeners.create(PreferenceChangeListener.class, this, prefs);
                prefs.addPreferenceChangeListener(weakPrefsListener);
            }
            
            // reload the settings
            preferenceChange(null);
        }
    }
    
    public void keyPressed(KeyEvent evt) {
        checkExpansionKeystroke(evt);
    }
    
    public void keyReleased(KeyEvent evt) {
        checkExpansionKeystroke(evt);
    }
    
    public void keyTyped(KeyEvent evt) {
        checkExpansionKeystroke(evt);
    }
    
    public void caretUpdate(CaretEvent evt) {
        if (evt.getDot() != evt.getMark()) {
            surroundsWithTimer.setInitialDelay(SURROUND_WITH_DELAY);
            surroundsWithTimer.restart();
        } else {
            surroundsWithTimer.stop();
            hideSurroundWithHint();
        }
    }

    private boolean isIgnoreModification() {
        return Boolean.TRUE.equals(doc.getProperty(ABBREV_IGNORE_MODIFICATION_DOC_PROPERTY));
    }
    
    private boolean isAbbrevDisabled() {
        return org.netbeans.editor.Abbrev.isAbbrevDisabled(component);
    }
    
    private void checkExpansionKeystroke(KeyEvent evt) {
        Position pos = null;
        Document d = null;
        synchronized (abbrevChars) {
            if (abbrevEndPosition != null && component != null && doc != null
                && component.getCaretPosition() == abbrevEndPosition.getOffset()
                && !isAbbrevDisabled()
                && doc.getProperty(EDITING_TEMPLATE_DOC_PROPERTY) == null
            ) {
                pos = abbrevEndPosition;
                d = component.getDocument();
            }
        }
        if (pos != null && d != null) {
            CodeTemplateManagerOperation operation = CodeTemplateManagerOperation.get(d, pos.getOffset());
            if (operation != null) {
                KeyStroke expandKeyStroke = operation.getExpansionKey();

                if (expandKeyStroke.equals(KeyStroke.getKeyStrokeForEvent(evt))) {
                    if (expand(operation)) {
                        evt.consume();
                    }
                }
            }
        }
    }

    /**
     * Get current abbreviation string.
     */
    private CharSequence getAbbrevText() {
        return abbrevChars;
    }

    /**
     * Reset abbreviation string collecting.
     */
    private void resetAbbrevChars() {
        synchronized(abbrevChars) {
            abbrevChars.setLength(0);
            abbrevEndPosition = null;
        }
    }
    
    private void appendTypedText(int offset, int insertLength) {
        if (abbrevEndPosition == null
            || offset + insertLength != abbrevEndPosition.getOffset()
        ) {
            // Does not follow previous insert
            resetAbbrevChars();
        }

        if (abbrevEndPosition == null) { // starting the new string
            try {
                // Start new accounting if previous char would reset abbrev
                // i.e. check that not start typing 'u' after existing 'p' which would
                // errorneously expand to 'public'
                if (offset == 0
                        || resetAcceptor.accept(DocumentUtilities.getText(doc, offset - 1, 1).charAt(0))
                ) {
                    abbrevEndPosition = doc.createPosition(offset + insertLength);
                }
            } catch (BadLocationException e) {
                ErrorManager.getDefault().notify(e);
            }
        }

        if (abbrevEndPosition != null) {
            try {
                String typedText = doc.getText(offset, insertLength); // typically just one char
                boolean textAccepted = true;
                for (int i = typedText.length() - 1; i >= 0; i--) {
                    if (resetAcceptor.accept(typedText.charAt(i))) {
                        // In theory there could be more than one character in the typed text
                        // and the resetting could occur on the very first char
                        // the next chars would not be accumulated as the insert
                        // is treated as a batch.
                        textAccepted = false;
                        break;
                    }
                }
                
                if (textAccepted) {
                    abbrevChars.append(typedText);
                    // abbrevEndPosition should move appropriately
                } else {
                    resetAbbrevChars();
                }

            } catch (BadLocationException e) {
                ErrorManager.getDefault().notify(e);
                resetAbbrevChars();
            }
        }
    }
    
    private void removeAbbrevText(int offset, int removeLength) {
        synchronized(abbrevChars) {
            if (abbrevEndPosition != null) {
                // Abbrev position should already move appropriately
                if (offset == abbrevEndPosition.getOffset()
                    && abbrevChars.length() >= removeLength
                ) { // removed at end
                    abbrevChars.setLength(abbrevChars.length() - removeLength);

                } else {
                    resetAbbrevChars();
                }
            }
        }
    }

    public boolean expand(CodeTemplateManagerOperation op) {
        CharSequence abbrevText = getAbbrevText();
        int abbrevEndOffset = abbrevEndPosition.getOffset();
        if (expand(op, component, abbrevEndOffset - abbrevText.length(), abbrevText)) {
            resetAbbrevChars();
            return true;
        } else {
            return false;
        }
    }
    
    private void showSurroundWithHint() {
        try {
            final Caret caret = component.getCaret();
            if (caret != null) {
                final Position pos = doc.createPosition(caret.getDot());
                RP.post(new Runnable() {
                    public void run() {
                        final List<Fix> fixes = SurroundWithFix.getFixes(component);
                        SwingUtilities.invokeLater(new Runnable() {
                            public void run() {
                                if (!fixes.isEmpty()) {
                                    errorDescription = ErrorDescriptionFactory.createErrorDescription(
                                            Severity.HINT, SURROUND_WITH, surrounsWithFixes = fixes, doc, pos, pos);

                                    HintsController.setErrors(doc, SURROUND_WITH, Collections.singleton(errorDescription));
                                } else {
                                    hideSurroundWithHint();
                                }
                            }
                        });
                    }
                });
            }
        } catch (BadLocationException ble) {
            Logger.getLogger("global").log(Level.WARNING, ble.getMessage(), ble);
        }
    }

    private void hideSurroundWithHint() {
        if (surrounsWithFixes != null)
            surrounsWithFixes = null;
        if (errorDescription != null) {
            errorDescription = null;
            HintsController.setErrors(doc, SURROUND_WITH, Collections.<ErrorDescription>emptySet());
        }
    }

    public static Acceptor getResetAcceptor(Preferences prefs, MimePath mimePath) {
        return prefs != null ? (Acceptor) callFactory(prefs, mimePath, "abbrev-reset-acceptor", AcceptorFactory.WHITESPACE) : AcceptorFactory.WHITESPACE; //NOI18N
    }

    // copied from org.netbeans.modules.editor.lib.SettingsConversions
    private static Object callFactory(Preferences prefs, MimePath mimePath, String settingName, Object defaultValue) {
        String factoryRef = prefs.get(settingName, null);
        
        if (factoryRef != null) {
            int lastDot = factoryRef.lastIndexOf('.'); //NOI18N
            assert lastDot != -1 : "Need fully qualified name of class with the static setting factory method."; //NOI18N

            String classFqn = factoryRef.substring(0, lastDot);
            String methodName = factoryRef.substring(lastDot + 1);

            ClassLoader loader = Lookup.getDefault().lookup(ClassLoader.class);
            try {
                Class factoryClass = loader.loadClass(classFqn);
                Method factoryMethod;
                
                try {
                    // normally the method should accept mime path and the a setting name
                    factoryMethod = factoryClass.getDeclaredMethod(methodName, MimePath.class, String.class);
                } catch (NoSuchMethodException nsme) {
                    // but there might be methods that don't need those params
                    try {
                        factoryMethod = factoryClass.getDeclaredMethod(methodName);
                    } catch (NoSuchMethodException nsme2) {
                        // throw the first exception complaining about the full signature
                        throw nsme;
                    }
                }
                
                Object value;
                if (factoryMethod.getParameterTypes().length == 2) {
                    value = factoryMethod.invoke(null, mimePath, settingName);
                } else {
                    value = factoryMethod.invoke(null);
                }
                
                if (value != null) {
                    return value;
                }
            } catch (Exception e) {
                LOG.log(Level.WARNING, null, e);
            }
        }

        return defaultValue;
    }

    private static boolean expand(CodeTemplateManagerOperation op, JTextComponent component, int abbrevStartOffset, CharSequence abbrev) {
        op.waitLoaded();
        CodeTemplate ct = op.findByAbbreviation(abbrev.toString());
        if (ct != null) {
            if (accept(ct, CodeTemplateManagerOperation.getTemplateFilters(component, abbrevStartOffset))) {
                Document doc = component.getDocument();
                sendUndoableEdit(doc, CloneableEditorSupport.BEGIN_COMMIT_GROUP);
                try {
                    // Remove the abbrev text
                    doc.remove(abbrevStartOffset, abbrev.length());
                    ct.insert(component);
                } catch (BadLocationException ble) {
                } finally {
                    sendUndoableEdit(doc, CloneableEditorSupport.END_COMMIT_GROUP);
                }
                return true;
            }
        }
        return false;
    }

    private static boolean accept(CodeTemplate template, Collection<? extends CodeTemplateFilter> filters) {
        for(CodeTemplateFilter filter : filters) {
            if (!filter.accept(template)) {
                return false;
            }
        }
        return true;
    }

    private static void sendUndoableEdit(Document d, UndoableEdit ue) {
        if(d instanceof AbstractDocument) {
            UndoableEditListener[] uels = ((AbstractDocument)d).getUndoableEditListeners();
            UndoableEditEvent ev = new UndoableEditEvent(d, ue);
            for(UndoableEditListener uel : uels) {
                uel.undoableEditHappened(ev);
            }
        }
    }
}
