/**
 * Copyright (c) 2014-2016 by the respective copyright holders.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.openhab.io.homekit.internal;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.builder.HashCodeBuilder;
import org.eclipse.smarthome.core.items.Item;
import org.eclipse.smarthome.core.items.ItemRegistry;
import org.eclipse.smarthome.core.library.items.DimmerItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Wraps an Item with data derived from supported tags defined.
 *
 * @author Andy Lintner
 */
public class HomekitTaggedItem {

    private static final Map<Integer, String> CREATED_ACCESSORY_IDS = new ConcurrentHashMap<>();

    private HomekitDeviceType homekitDeviceType;
    private HomekitCharacteristicType homekitCharacteristicType;
    private final Item item;
    private Logger logger = LoggerFactory.getLogger(HomekitTaggedItem.class);
    private final int id;

    public HomekitTaggedItem(Item item, ItemRegistry itemRegistry) {
        this.item = item;
        for (String tag : item.getTags()) {
            if (item instanceof DimmerItem) {
                tag = "Dimmable" + tag;
            }
            if (!isMemberOfRootGroup(item, itemRegistry)) {
                homekitDeviceType = HomekitDeviceType.valueOfTag(tag);
            }
            if (homekitDeviceType == null) {
                homekitCharacteristicType = HomekitCharacteristicType.valueOfTag(tag);
            }
        }
        if (homekitDeviceType != null) {
            this.id = calculateId(item);
        } else {
            this.id = 0;
        }
    }

    public boolean isTagged() {
        return (homekitDeviceType != null && id != 0) || homekitCharacteristicType != null;
    }

    public HomekitDeviceType getDeviceType() {
        return homekitDeviceType;
    }

    public HomekitCharacteristicType getCharacteristicType() {
        return homekitCharacteristicType;
    }

    public boolean isRootDevice() {
        return homekitDeviceType != null;
    }

    public boolean isCharacteristic() {
        return homekitCharacteristicType != null;
    }

    public Item getItem() {
        return item;
    }

    public int getId() {
        return id;
    }

    private int calculateId(Item item) {
        int id = new HashCodeBuilder().append(item.getName()).hashCode();
        if (id < 0) {
            id += Integer.MAX_VALUE;
        }
        if (id < 2) {
            id = 2; // 0 and 1 are reserved
        }
        if (CREATED_ACCESSORY_IDS.containsKey(id)) {
            if (!CREATED_ACCESSORY_IDS.get(id).equals(item.getName())) {
                logger.error("Could not create homekit accessory " + item.getName() + " "
                        + "because its hash conflicts with " + CREATED_ACCESSORY_IDS.get(id) + ". "
                        + "This is a 1:1,000,000 chance occurrence. Change one of the names and "
                        + "consider playing the lottery. See "
                        + "https://github.com/openhab/openhab2/issues/257#issuecomment-125886562");
                return 0;
            }
        } else {
            CREATED_ACCESSORY_IDS.put(id, item.getName());
        }
        return id;
    }

    private boolean isMemberOfRootGroup(Item item, ItemRegistry itemRegistry) {
        for (String groupName : item.getGroupNames()) {
            Item groupItem = itemRegistry.get(groupName);
            if (groupItem != null) {
                for (String groupTag : groupItem.getTags()) {
                    if (HomekitDeviceType.valueOfTag(groupTag) != null) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
}

@@ -1701,32 +1701,151 @@
 ;%0A            %7D%0A
+            if (homekitDeviceType != null %7C%7C homekitCharacteristicType != null) %7B%0A                break;%0A            %7D%0A
         %7D%0A      

Fix for multiple tags and HomeKit (#1138)