/**
 * 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.InputEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
import javax.swing.text.AbstractDocument;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import org.netbeans.api.editor.mimelookup.MimeLookup;
import org.netbeans.api.editor.mimelookup.MimePath;
import org.netbeans.api.editor.settings.CodeTemplateDescription;
import org.netbeans.api.editor.settings.CodeTemplateSettings;
import org.netbeans.api.lexer.TokenHierarchy;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.lib.editor.codetemplates.api.CodeTemplate;
import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
import org.netbeans.lib.editor.codetemplates.spi.*;
import org.netbeans.lib.editor.codetemplates.storage.CodeTemplateSettingsImpl;
import org.netbeans.modules.editor.NbEditorUtilities;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.RequestProcessor;
import org.openide.util.WeakListeners;

/**
 * Code template allows the client to paste itself into the given
 * text component.
 *
 * @author Miloslav Metelka
 */
public final class CodeTemplateManagerOperation
    implements LookupListener, Runnable
{
    private static final Logger LOG = Logger.getLogger(CodeTemplateManagerOperation.class.getName());
    
    private static final Map<MimePath, CodeTemplateManagerOperation> mime2operation = 
            new WeakHashMap<MimePath, CodeTemplateManagerOperation>(8);
    
    private static final KeyStroke DEFAULT_EXPANSION_KEY = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
    
    public static synchronized CodeTemplateManager getManager(Document doc) {
        String mimeType = (String)doc.getProperty("mimeType"); //NOI18N
        return get(MimePath.parse(mimeType)).getManager();
    }

    public static synchronized CodeTemplateManagerOperation get(Document document, int offset) {
        MimePath mimePath = getFullMimePath(document, offset);
        if (mimePath != null) {
            return CodeTemplateManagerOperation.get(mimePath);
        } else {
            return null;
        }
    }
    
    public static synchronized CodeTemplateManagerOperation get(MimePath mimePath) {
        CodeTemplateManagerOperation operation = mime2operation.get(mimePath);
        if (operation == null) {
            operation = new CodeTemplateManagerOperation(mimePath);
            mime2operation.put(mimePath, operation);
        }
        return operation;
    }
    
    private final CodeTemplateManager manager;
    private final String mimePath;
    private final Lookup.Result<CodeTemplateSettings> ctslr;
    private final EventListenerList listenerList = new EventListenerList();

    private boolean loaded = false;
    private Map<String, CodeTemplate> abbrev2template = Collections.<String, CodeTemplate>emptyMap();
    private List<CodeTemplate> sortedTemplatesByAbbrev = Collections.<CodeTemplate>emptyList();
    private List<CodeTemplate> sortedTemplatesByParametrizedText = Collections.<CodeTemplate>emptyList();
    private List<CodeTemplate> selectionTemplates = Collections.<CodeTemplate>emptyList();
    private KeyStroke expansionKey = DEFAULT_EXPANSION_KEY;
    private String expansionKeyText = getExpandKeyStrokeText(expansionKey);

    // Do not store mimePath in a private field, it would break the WeakHashMap cache
    private CodeTemplateManagerOperation(MimePath mimePath) {
        this.mimePath = mimePath.getPath();
        this.manager = CodeTemplateApiPackageAccessor.get().createCodeTemplateManager(this);
        assert manager != null : "Can't creat CodeTemplateManager"; //NOI18N
        
        this.ctslr = MimeLookup.getLookup(mimePath).lookupResult(CodeTemplateSettings.class);
        this.ctslr.addLookupListener(WeakListeners.create(LookupListener.class, this, this.ctslr));
        
        // Compute descriptions asynchronously
        RequestProcessor.getDefault().post(this);
    }
    
    public String getMimePath() {
        return mimePath;
    }
    
    public CodeTemplateManager getManager() {
        return manager;
    }
    
    public Collection<? extends CodeTemplate> getCodeTemplates() {
        return sortedTemplatesByAbbrev;
    }
    
    public Collection<? extends CodeTemplate> findSelectionTemplates() {
        return selectionTemplates;
    }
    
    public CodeTemplate findByAbbreviation(String abbreviation) {
        return abbrev2template.get(abbreviation);
    }
    
    public Collection<? extends CodeTemplate> findByAbbreviationPrefix(String prefix, boolean ignoreCase) {
        List<CodeTemplate> result = new ArrayList<CodeTemplate>();
        
        int low = 0;
	int high = sortedTemplatesByAbbrev.size() - 1;
	while (low <= high) {
	    int mid = (low + high) >> 1;
	    CodeTemplate t = sortedTemplatesByAbbrev.get(mid);
	    int cmp = compareTextIgnoreCase(t.getAbbreviation(), prefix);

	    if (cmp < 0) {
		low = mid + 1;
            } else if (cmp > 0) {
		high = mid - 1;
            } else {
                low = mid;
		break;
            }
	}
        
        // Go back whether prefix matches the name
        int i = low - 1;
        while (i >= 0) {
            CodeTemplate t = sortedTemplatesByAbbrev.get(i);
            int mp = matchPrefix(t.getAbbreviation(), prefix);
            if (mp == MATCH_NO) { // not matched
                break;
            } else if (mp == MATCH_IGNORE_CASE) { // matched when ignoring case
                if (ignoreCase) { // do not add if exact match required
                    result.add(t);
                }
            } else { // matched exactly
                result.add(t);
            }
            i--;
        }
        
        i = low;
        while (i < sortedTemplatesByAbbrev.size()) {
            CodeTemplate t = sortedTemplatesByAbbrev.get(i);
            int mp = matchPrefix(t.getAbbreviation(), prefix);
            if (mp == MATCH_NO) { // not matched
                break;
            } else if (mp == MATCH_IGNORE_CASE) { // matched when ignoring case
                if (ignoreCase) { // do not add if exact match required
                    result.add(t);
                }
            } else { // matched exactly
                result.add(t);
            }
            i++;
        }
        
        return result;
    }
    
    public Collection<? extends CodeTemplate> findByParametrizedText(String prefix, boolean ignoreCase) {
        List<CodeTemplate> result = new ArrayList<CodeTemplate>();
        
        int low = 0;
	int high = sortedTemplatesByParametrizedText.size() - 1;
	while (low <= high) {
	    int mid = (low + high) >> 1;
	    CodeTemplate t = sortedTemplatesByParametrizedText.get(mid);
	    int cmp = compareTextIgnoreCase(t.getParametrizedText(), prefix);

	    if (cmp < 0) {
		low = mid + 1;
            } else if (cmp > 0) {
		high = mid - 1;
            } else {
                low = mid;
		break;
            }
	}
        
        // Go back whether prefix matches the name
        int i = low - 1;
        while (i >= 0) {
            CodeTemplate t = sortedTemplatesByParametrizedText.get(i);
            int mp = matchPrefix(t.getParametrizedText(), prefix);
            if (mp == MATCH_NO) { // not matched
                break;
            } else if (mp == MATCH_IGNORE_CASE) { // matched when ignoring case
                if (ignoreCase) { // do not add if exact match required
                    result.add(t);
                }
            } else { // matched exactly
                result.add(t);
            }
            i--;
        }
        
        i = low;
        while (i < sortedTemplatesByParametrizedText.size()) {
            CodeTemplate t = sortedTemplatesByParametrizedText.get(i);
            int mp = matchPrefix(t.getParametrizedText(), prefix);
            if (mp == MATCH_NO) { // not matched
                break;
            } else if (mp == MATCH_IGNORE_CASE) { // matched when ignoring case
                if (ignoreCase) { // do not add if exact match required
                    result.add(t);
                }
            } else { // matched exactly
                result.add(t);
            }
            i++;
        }
        
        return result;
    }
    
    public static Collection<? extends CodeTemplateFilter> getTemplateFilters(JTextComponent component, int offset) {
        MimePath mimeType = getFullMimePath(component.getDocument(), offset);
        Collection<? extends CodeTemplateFilter.Factory> filterFactories = 
            MimeLookup.getLookup(mimeType).lookupAll(CodeTemplateFilter.Factory.class);
        
        List<CodeTemplateFilter> result = new ArrayList<CodeTemplateFilter>(filterFactories.size());
        for (CodeTemplateFilter.Factory factory : filterFactories) {
            result.add(factory.createFilter(component, offset));
        }
        return result;
    }

    public static void insert(CodeTemplate codeTemplate, JTextComponent component) {
        String mimePath = CodeTemplateApiPackageAccessor.get().getCodeTemplateMimePath(codeTemplate);
        Collection<? extends CodeTemplateProcessorFactory> processorFactories = 
            MimeLookup.getLookup(mimePath).lookupAll(CodeTemplateProcessorFactory.class);
        
        CodeTemplateInsertHandler handler = new CodeTemplateInsertHandler(
                codeTemplate, component, processorFactories, CodeTemplateSettingsImpl.get(MimePath.parse(mimePath)).getOnExpandAction());
        handler.processTemplate();
    }
    
    /**
     * Match text against the given prefix.
     *
     * @param text text to be compared with the prefix.
     * @param prefix text to be matched as a prefix of the text parameter.
     * @return one of <code>MATCH_NO</code>, <code>MATCH_IGNORE_CASE</code>
     *  or <code>MATCH</code>
     */
    private static final int MATCH_NO = 0;
    private static final int MATCH_IGNORE_CASE = 1;
    private static final int MATCH = 2;
    private static int matchPrefix(CharSequence text, CharSequence prefix) {
        boolean matchCase = true;
        int prefixLength = prefix.length();
        if (prefixLength > text.length()) { // prefix longer than text
            return MATCH_NO;
        }
        int i;
        for (i = 0; i < prefixLength; i++) {
            char ch1 = text.charAt(i);
            char ch2 = prefix.charAt(i);
            if (ch1 != ch2) {
                matchCase = false;
                if (Character.toLowerCase(ch1) != Character.toLowerCase(ch2)) {
                    break;
                }
            }
        }
        if (i == prefixLength) { // compared all
            return matchCase ? MATCH : MATCH_IGNORE_CASE;
        } else { // not compared all => not matched
            return MATCH_NO;
        }
    }
    
    private static int compareTextIgnoreCase(CharSequence text1, CharSequence text2) {
        int len = Math.min(text1.length(), text2.length());
        for (int i = 0; i < len; i++) {
            char ch1 = Character.toLowerCase(text1.charAt(i));
            char ch2 = Character.toLowerCase(text2.charAt(i));
            if (ch1 != ch2) {
                return ch1 - ch2;
            }
        }
        return text1.length() - text2.length();
    }
    
    public boolean isLoaded() {
        synchronized (listenerList) {
            return loaded;
        }
    }
    
    public void registerLoadedListener(ChangeListener listener) {
        synchronized (listenerList) {
            if (!isLoaded()) {
                // not yet loaded
                listenerList.add(ChangeListener.class, listener);
                return;
            }
        }

        // already loaded
        listener.stateChanged(new ChangeEvent(manager));
    }
    
    public void waitLoaded() {
        synchronized (listenerList) {
            while(!isLoaded()) {
                try {
                    listenerList.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException("Interrupted when waiting to load code templates"); //NOI18N
                }
            }
        }
    }
    
    private void fireStateChanged(ChangeEvent evt) {
        Object[] listeners;
        synchronized (listenerList) {
            listeners = listenerList.getListenerList();
        }
        for (int i = 0; i < listeners.length; i += 2) {
            if (ChangeListener.class == listeners[i]) {
                ((ChangeListener)listeners[i + 1]).stateChanged(evt);
            }
        }
    }
    
    public void run() {
        rebuildCodeTemplates();
    }
    
    private static void processCodeTemplateDescriptions(
        CodeTemplateManagerOperation operation,
        Collection<? extends CodeTemplateDescription> ctds,
        Map<String, CodeTemplate> codeTemplatesMap,
        List<CodeTemplate> codeTemplatesWithSelection
    ) {
        for (CodeTemplateDescription ctd : ctds) {
            CodeTemplate ct = CodeTemplateApiPackageAccessor.get().createCodeTemplate(
                operation, 
                ctd.getAbbreviation(),
                ctd.getDescription(), 
                ctd.getParametrizedText(),
                ctd.getContexts(),
                ctd.getMimePath()
            );
            
            codeTemplatesMap.put(ct.getAbbreviation(), ct);
            if (ct.getParametrizedText().toLowerCase().indexOf("${selection") > -1) { //NOI18N
                codeTemplatesWithSelection.add(ct);
            }
        }
    }
    
    private void rebuildCodeTemplates() {
        Collection<? extends CodeTemplateSettings> allCts = ctslr.allInstances();
        CodeTemplateSettings cts = allCts.isEmpty() ? null : allCts.iterator().next();
        
        Map<String, CodeTemplate> map = new HashMap<String, CodeTemplate>();
        List<CodeTemplate> templatesWithSelection = new ArrayList<CodeTemplate>();
        KeyStroke keyStroke = DEFAULT_EXPANSION_KEY;
        
        if (cts != null) {
            // Load templates
            Collection<? extends CodeTemplateDescription> ctds = cts.getCodeTemplateDescriptions();
            processCodeTemplateDescriptions(this, ctds, map, templatesWithSelection);
            
            // Load expansion key
            keyStroke = patchExpansionKey(cts.getExpandKey());
        } else {
            if (LOG.isLoggable(Level.WARNING)) {
                LOG.warning("Can't find CodeTemplateSettings for '" + mimePath + "'"); //NOI18N
            }
        }

        List<CodeTemplate> byAbbrev = new ArrayList<CodeTemplate>(map.values());
        Collections.sort(byAbbrev, CodeTemplateComparator.BY_ABBREVIATION_IGNORE_CASE);

        List<CodeTemplate> byText = new ArrayList<CodeTemplate>(map.values());
        Collections.sort(byText, CodeTemplateComparator.BY_PARAMETRIZED_TEXT_IGNORE_CASE);
        
        Collections.sort(templatesWithSelection, CodeTemplateComparator.BY_PARAMETRIZED_TEXT_IGNORE_CASE);

        boolean fire = false;

        synchronized(listenerList) {
            fire = abbrev2template == null;

            abbrev2template = Collections.unmodifiableMap(map);
            sortedTemplatesByAbbrev = Collections.unmodifiableList(byAbbrev);
            sortedTemplatesByParametrizedText = Collections.unmodifiableList(byText);
            selectionTemplates = Collections.unmodifiableList(templatesWithSelection);
            expansionKey = keyStroke;
            expansionKeyText = getExpandKeyStrokeText(keyStroke);
            
            loaded = true;
            listenerList.notifyAll();
        }

        if (fire) {
            fireStateChanged(new ChangeEvent(manager));
        }
    }
    
    public KeyStroke getExpansionKey() {
        return expansionKey;
    }

    public String getExpandKeyStrokeText() {
        return expansionKeyText;
    }
    
    private static String getExpandKeyStrokeText(KeyStroke keyStroke) {
        String expandKeyStrokeText;
        if (keyStroke.equals(KeyStroke.getKeyStroke(' '))) { //NOI18N
            expandKeyStrokeText = "SPACE"; // NOI18N
        } else if (keyStroke.equals(KeyStroke.getKeyStroke(new Character(' '), InputEvent.SHIFT_MASK))) { //NOI18N
            expandKeyStrokeText = "Shift-SPACE"; // NOI18N
        } else if (keyStroke.equals(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0))) {
            expandKeyStrokeText = "TAB"; // NOI18N
        } else if (keyStroke.equals(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0))) {
            expandKeyStrokeText = "ENTER"; // NOI18N
        } else {
            expandKeyStrokeText = keyStroke.toString();
        }
        return expandKeyStrokeText;
    }
    
    private static KeyStroke patchExpansionKey(KeyStroke eks) {
	// Patch the keyPressed => keyTyped to prevent insertion of expand chars into editor
        if (eks.equals(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0))) {
            eks = KeyStroke.getKeyStroke(' ');
        } else if (eks.equals(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_MASK))) {
            eks = KeyStroke.getKeyStroke(new Character(' '), InputEvent.SHIFT_MASK);
        } else if (eks.equals(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0))) {
        } else if (eks.equals(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0))) {
        }
	return eks;
    }
    
    public void resultChanged(LookupEvent ev) {
        rebuildCodeTemplates();
    }
    
    private static MimePath getFullMimePath(Document document, int offset) {
        String langPath = null;

        if (document instanceof AbstractDocument) {
            AbstractDocument adoc = (AbstractDocument)document;
            adoc.readLock();
            try {
                List<TokenSequence<?>> list = TokenHierarchy.get(document).embeddedTokenSequences(offset, true);
                if (list.size() > 1) {
                    langPath = list.get(list.size() - 1).languagePath().mimePath();
                }
            } finally {
                adoc.readUnlock();
            }
        }

        if (langPath == null) {
            langPath = NbEditorUtilities.getMimeType(document);
        }

        if (langPath != null) {
            return MimePath.parse(langPath);
        } else {
            return null;
        }
    }
}
