/*
 * 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.apache.qpid.jms;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.qpid.jms.jndi.JNDIStorable;

/**
 * Jms Destination
 */
public abstract class JmsDestination extends JNDIStorable implements Externalizable, jakarta.jms.Destination, Comparable<JmsDestination> {
    private static final String NAME_PROP = "address";
    private static final String LEGACY_NAME_PROP = "name";

    protected transient String address;
    protected transient boolean topic;
    protected transient boolean temporary;
    protected transient int hashValue;
    protected transient JmsConnection connection;

    protected JmsDestination(String address, boolean topic, boolean temporary) {
        this.address = address;
        this.topic = topic;
        this.temporary = temporary;
    }

    @Override
    public String toString() {
        return address;
    }

    /**
     * @return address of destination
     */
    public String getAddress() {
        return this.address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    /**
     * @return the topic
     */
    public boolean isTopic() {
        return this.topic;
    }

    /**
     * @return the temporary
     */
    public boolean isTemporary() {
        return this.temporary;
    }

    /**
     * @return true if a Topic
     */
    public boolean isQueue() {
        return !this.topic;
    }

    @Override
    protected Map<String, String> buildFromProperties(Map<String, String> props) {
        setAddress(getProperty(props, NAME_PROP, getProperty(props, LEGACY_NAME_PROP, "")));

        Map<String, String> unused = new HashMap<String,String>(props);
        unused.remove(NAME_PROP);
        unused.remove(LEGACY_NAME_PROP);

        return Collections.unmodifiableMap(unused);
    }

    @Override
    protected void populateProperties(Map<String, String> props) {
        props.put(NAME_PROP, getAddress());
    }

    /**
     * @param other
     *        the Object to be compared.
     * @return a negative integer, zero, or a positive integer as this object is
     *         less than, equal to, or greater than the specified object.
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     */
    @Override
    public int compareTo(JmsDestination other) {
        if (other != null) {
            if (this == other) {
                return 0;
            }
            if (isTemporary() == other.isTemporary()) {
                return getAddress().compareTo(other.getAddress());
            }
            return -1;
        }
        return -1;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        JmsDestination other = (JmsDestination) o;
        if (address == null && other.address != null) {
            return false;
        } else if (address != null && !address.equals(other.address)) {
            return false;
        }

        if (temporary != other.temporary) {
            return false;
        }
        if (topic != other.topic) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        if (hashValue == 0) {
            final int prime = 31;
            hashValue = 1;
            hashValue = prime * hashValue + ((address == null) ? 0 : address.hashCode());
            hashValue = prime * hashValue + (temporary ? 1231 : 1237);
            hashValue = prime * hashValue + (topic ? 1231 : 1237);
        }
        return hashValue;
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(getAddress());
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        setAddress(in.readUTF());
    }
}
