/**
 * 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.modules.editor.macros;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.KeyStroke;
import org.netbeans.api.editor.mimelookup.MimePath;
import org.netbeans.api.editor.settings.MultiKeyBinding;
import org.netbeans.modules.editor.macros.storage.MacroDescription;
import org.netbeans.modules.editor.macros.storage.MacrosStorage;
import org.netbeans.modules.editor.settings.storage.api.EditorSettingsStorage;
import org.netbeans.modules.editor.settings.storage.spi.StorageFilter;
import org.openide.util.Lookup;
import org.openide.util.RequestProcessor;
import org.openide.util.WeakListeners;

/**
 *
 * @author Vita Stejskal
 */
@org.openide.util.lookup.ServiceProvider(service=org.netbeans.modules.editor.settings.storage.spi.StorageFilter.class)
public final class MacroShortcutsInjector extends StorageFilter<Collection<KeyStroke>, MultiKeyBinding> implements PropertyChangeListener {
    /**
     * How many times the Injector will try to load the macros from the editor storage.
     * Because of issue #223802, editor storage may not be yet initialized when the Injector is run.
     */
    private static final int MAX_RETRY_COUNT = 2;
    
    public static void refreshShortcuts() {
        Collection<? extends MacroShortcutsInjector> injectors = Lookup.getDefault().lookupAll(MacroShortcutsInjector.class);
        if (injectors.size() == 0) {
            LOG.warning("No MacroShortcutsInjector found in default Lookup"); //NOI18N
            return;
        } else if (injectors.size() > 1) {
            LOG.warning("Too many MacroShortcutsInjector instances found in default Lookup:"); //NOI18N
            for(MacroShortcutsInjector msi : injectors) {
                LOG.warning("  " + msi); //NOI18N
            }
        }

        injectors.iterator().next().notifyChanges();
//        assert instance != null;
//        LOG.fine("Shortcuts refresh forced, notifying 'Keybindings' storage..."); //NOI18N
//        instance.notifyChanges();
    }
    
    public MacroShortcutsInjector() {
        super("Keybindings"); //NOI18N
    }
    
    // ------------------------------------------------------------------------
    // StorageFilter implementation
    // ------------------------------------------------------------------------
    
    @Override
    public void afterLoad(Map<Collection<KeyStroke>, MultiKeyBinding> map, MimePath mimePath, String profile, boolean defaults) {
        Map<String, MacroDescription> macros = new HashMap<String, MacroDescription>();
        if (!collectMacroActions(mimePath, macros)) {
            return;
        }
        
        for(MacroDescription macro : macros.values()) {
            List<? extends MultiKeyBinding> shortcuts = macro.getShortcuts();
            for(MultiKeyBinding shortcut : shortcuts) {
                Collection<KeyStroke> keys = shortcut.getKeyStrokeList();

                // A macro shortcut never replaces shortcuts for ordinary editor actions
                if (!map.containsKey(keys)) {
                    map.put(keys, shortcut);
                    if (LOG.isLoggable(Level.FINE)) {
                        LOG.fine("afterLoad: injecting " + keys + " for macro '" //NOI18N
                            + macro.getName() + "'; mimePath='" + mimePath.getPath() + "'"); //NOI18N
                    }
                } else {
                    LOG.warning("Shortcut " + keys + " is bound to '" + map.get(keys).getActionName() //NOI18N
                        + "' for '" + mimePath.getPath() + "' and will not be assigned to '" + macro.getName() + "' macro!"); //NOI18N
                }
            }
        }
    }

    @Override
    public void beforeSave(Map<Collection<KeyStroke>, MultiKeyBinding> map, MimePath mimePath, String profile, boolean defaults) {
        Set<Collection<KeyStroke>> keysToFilterOut = new HashSet<Collection<KeyStroke>>();
        
        for(Collection<KeyStroke> keys : map.keySet()) {
            MultiKeyBinding shortcut = map.get(keys);
            if (shortcut.getActionName().equals(MacroDialogSupport.RunMacroAction.runMacroAction)) {
                keysToFilterOut.add(keys);
                if (LOG.isLoggable(Level.FINE)) {
                    LOG.fine("beforeSave: filtering out macro shortcut " + keys + "; mimePath='" + mimePath.getPath() + "'"); //NOI18N
                }
            }
        }
        
        map.keySet().removeAll(keysToFilterOut);
    }

    // ------------------------------------------------------------------------
    // PropertyChangeListener implementation
    // ------------------------------------------------------------------------
    
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName() == null || EditorSettingsStorage.PROP_DATA.equals(evt.getPropertyName())) {
            LOG.fine("Macros storage changed, notifying 'Keybindings' storage...");
            notifyChanges();
        }
    }
    
    // ------------------------------------------------------------------------
    // private implementation
    // ------------------------------------------------------------------------
    
    private static final Logger LOG = Logger.getLogger(MacroShortcutsInjector.class.getName());
    
    private EditorSettingsStorage<String, MacroDescription> storage = null;
    
    /**
     * Counter of attempted refreshes
     */
    private int retryCount;
    
    private RequestProcessor.Task delayed;
    
    private boolean collectMacroActions(MimePath mimePath, Map<String, MacroDescription> macros) {
        if (storage == null) {
            storage = EditorSettingsStorage.<String, MacroDescription>find(MacrosStorage.ID);
            if (storage == null) {
                synchronized (this) {
                    if (delayed != null) {
                        return false;
                    }
                    if (retryCount++ < MAX_RETRY_COUNT) {
                        delayed = RequestProcessor.getDefault().post(new Runnable() {
                            public void run() {
                                synchronized (MacroShortcutsInjector.this) {
                                    delayed = null;
                                }
                                refreshShortcuts();
                            }
                        }, 500);
                    } else {
                        LOG.warning("Could not create macro shortcuts, editor settings storage not initialized yet.");
                    }
                }
                return false;
            }
            storage.addPropertyChangeListener(WeakListeners.propertyChange(this, storage));
        }

        try {
            macros.putAll(storage.load(mimePath, null, false));
        } catch (IOException ioe) {
            LOG.log(Level.WARNING, null, ioe);
        }
        return true;
    }

}
