//   Copyright 2012 Georg-August-Universität Göttingen, Germany
//
//   Licensed 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 de.ugoe.cs.autoquest.keyboardmaps;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

import de.ugoe.cs.util.console.Console;

/**
 * <p>
 * Helper class to handle synonymous {@link VirtualKey}s.
 * </p>
 * 
 * @version 1.0
 * @author Patrick Harms
 */
class VirtualKeySynonyms {

    /**
     * <p>
     * Map of synonymous keys.
     * </p>
     */
    private Map<Integer, List<VirtualKey>> synonyms = new HashMap<Integer, List<VirtualKey>>();

    /**
     * <p>
     * Mapping of {@link VirtualKey}s to integer Ids.
     * </p>
     */
    private Map<VirtualKey, Integer> keyIds = new HashMap<VirtualKey, Integer>();

    /**
     * <p>
     * Adds a new synonymous key.
     * </p>
     * 
     * @param keyId
     *            id of the synonym
     * @param virtualKey
     *            the synonym
     */
    public void add(int keyId, VirtualKey virtualKey) {
        List<VirtualKey> synonymList = synonyms.get(keyId);

        if (synonymList == null) {
            synonymList = new ArrayList<VirtualKey>();
            synonyms.put(keyId, synonymList);
        }

        if (!synonymList.contains(virtualKey)) {
            // ensure that the latest determined virtual keys are considered first
            synonymList.add(0, virtualKey);
        }

        Integer existingKeyId = keyIds.get(virtualKey);

        if ((existingKeyId != null) && (existingKeyId != keyId)) {
            Console.traceln(Level.FINEST, "virtual key " + virtualKey + " is mapped to more " +
                "than one key id (current is " + existingKeyId + ", new is " + keyId +
                "). New key id will be used (" + keyId + ").");
        }

        keyIds.put(virtualKey, keyId);
    }

    /**
     * <p>
     * Returns whether a key is contained in the set of synonyms.
     * </p>
     * 
     * @param keyId
     *            id of the key
     * @return true, if the key is contained; false otherwise
     */
    public boolean containsKey(int keyId) {
        return synonyms.containsKey(keyId);
    }

    /**
     * <p>
     * Returns all synonyms known for a given key.
     * </p>
     * 
     * @param keyId
     *            the id of the key
     * @return the synonyms
     */
    public VirtualKey[] getVirtualKeySynonyms(int keyId) {
        List<VirtualKey> virtualKeys = synonyms.get(keyId);
        if (virtualKeys != null) {
            return virtualKeys.toArray(new VirtualKey[virtualKeys.size()]);
        }
        else {
            Console.traceln(Level.WARNING, "no virtual key define for key id " + keyId);
            return null;
        }
    }

}
