/**
 * Copyright (c) 2014,2018 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.eclipse.smarthome.binding.bosesoundtouch.internal;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringEscapeUtils;

import com.google.gson.annotations.Expose;

/**
 * The {@link ContentItem} class manages a ContentItem
 *
 * @author Christian Niessner - Initial contribution
 * @author Thomas Traunbauer - Initial contribution
 */
public class ContentItem {

    private String source;
    private String sourceAccount;
    private String location;
    private boolean presetable;
    private String itemName;
    private int presetID;
    @Expose
    private Map<String, String> additionalAttributes;

    /**
     * Creates a new instance of this class
     */
    public ContentItem() {
        source = "";
        sourceAccount = null;
        location = null;
        presetable = false;
        itemName = null;
        presetID = 0;
        additionalAttributes = new HashMap<>();
    }

    /**
     * Returns true if this ContentItem is defined as Preset
     *
     * @return true if this ContentItem is defined as Preset
     */
    public boolean isPreset() {
        if (presetable) {
            return presetID > 0;
        } else {
            return false;
        }
    }

    /**
     * Returns true if all necessary stats are set
     *
     * @return true if all necessary stats are set
     */
    public boolean isValid() {
        if (getOperationMode() == OperationModeType.STANDBY) {
            return true;
        }
        if (itemName.equals("") || source.equals("")) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * Returns true if source, sourceAccount, location, itemName, and presetable are equal
     *
     * @return true if source, sourceAccount, location, itemName, and presetable are equal
     */
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof ContentItem) {
            ContentItem other = (ContentItem) obj;
            if (!isEqual(other.source, this.source)) {
                return false;
            }
            if (!isEqual(other.sourceAccount, this.sourceAccount)) {
                return false;
            }
            if (other.presetable != this.presetable) {
                return false;
            }
            if (!isEqual(other.location, this.location)) {
                return false;
            }
            if (!isEqual(other.itemName, this.itemName)) {
                return false;
            }
            return true;
        }
        return super.equals(obj);
    }

    /**
     * Returns the operation Mode, depending on the stats that are set
     *
     * @return the operation Mode, depending on the stats that are set
     */
    public OperationModeType getOperationMode() {
        OperationModeType operationMode = OperationModeType.OTHER;
        if (source == null || source.equals("")) {
            return OperationModeType.OTHER;
        }
        if (source.contains("PRODUCT")) {
            if (sourceAccount.contains("TV")) {
                operationMode = OperationModeType.TV;
            }
            if (sourceAccount.contains("HDMI")) {
                operationMode = OperationModeType.HDMI1;
            }
            return operationMode;
        }
        try {
            operationMode = OperationModeType.valueOf(source);
            return operationMode;
        } catch (IllegalArgumentException iae) {
            return OperationModeType.OTHER;
        }
    }

    public void setSource(String source) {
        this.source = source;
    }

    public void setSourceAccount(String sourceAccount) {
        this.sourceAccount = sourceAccount;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public void setAdditionalAttribute(String name, String value) {
        this.additionalAttributes.put(name, value);
    }

    public void setPresetable(boolean presetable) {
        this.presetable = presetable;
    }

    public void setPresetID(int presetID) {
        this.presetID = presetID;
    }

    public String getSource() {
        return source;
    }

    public String getSourceAccount() {
        return sourceAccount;
    }

    public String getLocation() {
        return location;
    }

    public String getItemName() {
        return itemName;
    }

    public boolean isPresetable() {
        return presetable;
    }

    public int getPresetID() {
        return presetID;
    }

    /**
     * Returns the XML Code that is needed to switch to this ContentItem
     *
     * @return the XML Code that is needed to switch to this ContentItem
     */
    public String generateXML() {
        String xml;
        switch (getOperationMode()) {
            case BLUETOOTH:
                xml = "<ContentItem source=\"BLUETOOTH\"></ContentItem>";
                break;
            case AUX:
            case AUX1:
            case AUX2:
            case AUX3:
                xml = "<ContentItem source=\"AUX\" sourceAccount=\"" + sourceAccount + "\"></ContentItem>";
                break;
            case TV:
                xml = "<ContentItem source=\"PRODUCT\" sourceAccount=\"TV\" isPresetable=\"false\" />";
                break;
            case HDMI1:
                xml = "<ContentItem source=\"PRODUCT\" sourceAccount=\"HDMI_1\" isPresetable=\"false\" />";
                break;
            default:
                StringBuilder sbXml = new StringBuilder("<ContentItem");
                if (source != null) {
                    sbXml.append(" source=\"").append(StringEscapeUtils.escapeXml(source)).append("\"");
                }
                if (location != null) {
                    sbXml.append(" location=\"").append(StringEscapeUtils.escapeXml(location)).append("\"");
                }
                if (sourceAccount != null) {
                    sbXml.append(" sourceAccount=\"").append(StringEscapeUtils.escapeXml(sourceAccount)).append("\"");
                }
                sbXml.append(" isPresetable=\"").append(presetable).append("\"");
                for (Map.Entry<String, String> aae : additionalAttributes.entrySet()) {
                    sbXml.append(" ").append(aae.getKey()).append("=\"")
                            .append(StringEscapeUtils.escapeXml(aae.getValue())).append("\"");
                }
                sbXml.append(">");
                if (itemName != null) {
                    sbXml.append("<itemName>").append(itemName).append("</itemName>");
                }
                sbXml.append("</ContentItem>");
                xml = sbXml.toString();
                break;
        }
        return xml;
    }

    @Override
    public String toString() {
        // if (presetID >= 1 && presetID <= 6) {
        // StringBuilder buffer = new StringBuilder();
        // buffer.append("PRESET_");
        // buffer.append(presetID);
        // return buffer.toString();
        // }
        return itemName;
    }

    private boolean isEqual(String s1, String s2) {
        if (s1 == s2) {
            return true;
        }
        if (s1 == null || s2 == null) {
            return false;
        }
        return s1.equals(s2);
    }
}

@@ -1015,16 +1015,22 @@
 private 
+final 
 Map%3CStri
@@ -1927,26 +1927,63 @@
 itemName
-.equals(%22%22
+ == null %7C%7C source == null %7C%7C itemName.isEmpty(
 ) %7C%7C sou
@@ -1982,33 +1982,32 @@
 ) %7C%7C source.
-equals(%22%22
+isEmpty(
 )) %7B%0A       

Fix NPE (#5685)