package net.onrc.onos.core.topology;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.commons.lang.Validate;

/**
 * Base class for Topology Elements.
 * <p/>
 * Self-contained element, it is expected to be used as if it is an immutable
 * object.
 *
 * @param <T> Sub-class' type.
 *      (Required to define a method returning itself's type)
 */
public class TopologyElement<T extends TopologyElement<T>>
        implements ITopologyElement, StringAttributes, UpdateStringAttributes {

    // TODO: Where should the attribute names be defined?
    /**
     * Attribute name for type.
     */
    public static final String TYPE = "type";
    /**
     * Attribute "type" value representing that the object belongs to Packet
     * layer.
     */
    public static final String TYPE_PACKET_LAYER = "packet";
    /**
     * Attribute "type" value representing that the object belongs to Optical
     * layer.
     */
    public static final String TYPE_OPTICAL_LAYER = "optical";
    /**
     * Attribute "type" value representing that the object belongs to all
     * layers.
     */
    public static final String TYPE_ALL_LAYERS = "AllLayers";

    public static final String ELEMENT_CONFIG_STATE = "ConfigState";

    public static final String ELEMENT_ADMIN_STATUS = "AdminStatus";

    /**
     * Attribute name for device type.
     */
    public static final String ELEMENT_TYPE = "ElementType";

    private boolean isFrozen = false;

    private ConcurrentMap<String, String> stringAttributes;



    /**
     * Default constructor for serializer.
     */
    protected TopologyElement() {
        this.isFrozen = false;
        this.stringAttributes = new ConcurrentHashMap<>();
    }

    /**
     * Creates an unfrozen copy of given Object.
     * <p/>
     * Sub-classes should do a deep-copies if necessary.
     *
     * @param original to make copy of.
     */
    public TopologyElement(TopologyElement<T> original) {
        this.isFrozen = false;
        this.stringAttributes = new ConcurrentHashMap<>(original.stringAttributes);

    }


    /**
     * Tests if this instance is frozen.
     *
     * @return true if frozen.
     */
    public boolean isFrozen() {
        return isFrozen;
    }

    /**
     * Freezes this instance to avoid further modifications.
     *
     * @return this
     */
    @SuppressWarnings("unchecked")
    public T freeze() {
        isFrozen = true;
        return (T) this;
    }

    @Override
    public int hashCode() {
        return stringAttributes.hashCode();
    }

    /*
     *  (non-Javadoc)
     * Equality based only on string attributes.
     *
     * Subclasses should call super.equals().
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        @SuppressWarnings("unchecked")
        TopologyElement<T> other = (TopologyElement<T>) obj;
        return Objects.equals(stringAttributes, other.stringAttributes);
    }

    @Override
    public String getStringAttribute(String attr) {
        return this.stringAttributes.get(attr);
    }

    @Override
    public String getStringAttribute(String attr, String def) {
        final String v = getStringAttribute(attr);
        if (v == null) {
            return def;
        } else {
            return v;
        }
    }

    @Override
    public Map<String, String> getAllStringAttributes() {
        return Collections.unmodifiableMap(this.stringAttributes);
    }

    @Override
    public boolean createStringAttribute(String attr, String value) {
        if (isFrozen) {
            throw new IllegalStateException("Tried to modify frozen object: " + this);
        }
        Validate.notNull(value, "attribute value cannot be null");

        return this.stringAttributes.putIfAbsent(attr, value) == null;
    }

    @Override
    public boolean replaceStringAttribute(String attr, String oldValue, String value) {
        if (isFrozen) {
            throw new IllegalStateException("Tried to modify frozen object: " + this);
        }
        Validate.notNull(value, "attribute value cannot be null");

        return this.stringAttributes.replace(attr, oldValue, value);
    }

    @Override
    public boolean deleteStringAttribute(String attr, String expectedValue) {
        if (isFrozen) {
            throw new IllegalStateException("Tried to modify frozen object: " + this);
        }

        return this.stringAttributes.remove(attr, expectedValue);
    }

    @Override
    public void deleteStringAttribute(String attr) {
        if (isFrozen) {
            throw new IllegalStateException("Tried to modify frozen object: " + this);
        }

        this.stringAttributes.remove(attr);
    }

    @Override
    public String getType() {
        return getStringAttribute(TYPE, TYPE_PACKET_LAYER);
    }

    /**
     * Returns the config state of topology element.
     *
     * @return ConfigState
     */
    @Override
    public ConfigState getConfigState() {
        return ConfigState.valueOf(getStringAttribute(ELEMENT_CONFIG_STATE));
    }

    /**
     * Returns the status of topology element.
     *
     * @return AdminStatus
     */
    @Override
    public AdminStatus getStatus() {
        return AdminStatus.valueOf(getStringAttribute(ELEMENT_ADMIN_STATUS));
    }

}
