/*
 * RHQ Management Platform
 * Copyright (C) 2005-2011 Red Hat, Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package org.rhq.modules.plugins.jbossas7.json;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.codehaus.jackson.annotate.JsonIgnore;

/**
 * An address in AS7
 * @author Heiko W. Rupp
 */
public class Address {

    /** List of individual path components */
    List<PROPERTY_VALUE> path;

    /** Create an empty address */
    public Address() {
        path = new ArrayList<PROPERTY_VALUE>();
    }

    /**
     * Create an Address with an intial path element
     * @param key key part of the path
     * @param value value part of the path
     */
    public Address(String key, String value) {
        this();
        add(key,value);
    }

    /**
     * Construct an Addres by cloning another
     * @param other Address to clone
     */
    public Address(Address other) {
        this();
        if (other!=null && other.path!=null)
            path.addAll(other.path);
    }

    /**
     * Construct an address from the passed list of path segments of property values. Should not be used
     * outside the json package
     * @param property_values list of values, each describing a key-value pair of a path
     */
    Address(List<PROPERTY_VALUE> property_values) {
        this();
        if (property_values!=null)
            path.addAll(property_values);
    }

    /**
     * Construct an Address from a path in the form (key=value)?(,key=value)*
     * @param path Path string to parse
     */
    public Address(String path) {
        this();
        if (path==null || path.isEmpty())
            return;
        String[] components = path.split(",");
        for (String component : components) {
            String tmp = component.trim();

            if (tmp.contains("=")) {
                // strip / from the start of the key if it happens to be there
                if (tmp.startsWith("/"))
                    tmp = tmp.substring(1);

                String[] pair = tmp.split("=");
                PROPERTY_VALUE valuePair = new PROPERTY_VALUE(pair[0], pair[1]);
                this.path.add(valuePair);
            }
        }

    }

    /**
     * Add a key value pair to the path
     * @param key Key part of this path element
     * @param value Value part of this path element
     */
    public void add(String key, String value) {
        path.add(new PROPERTY_VALUE(key,value));
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder( "Address{" +
            "path: " );
        if (path!=null) {
            Iterator<PROPERTY_VALUE> iterator = path.iterator();
            while (iterator.hasNext()) {
                PROPERTY_VALUE pv = iterator.next();
                builder.append(pv.getKey()).append('=').append(pv.getValue());
                if (iterator.hasNext())
                    builder.append(',');
            }
        }
        else {
            builder.append("-empty-");
        }

        builder.append('}');
        return builder.toString();
    }

    /**
     * Returns the Address as a string
     * @return list of key value pairs for this path
     */
    @JsonIgnore
    public String getPath() {
        StringBuilder builder = new StringBuilder();
        Iterator<PROPERTY_VALUE> iter = path.iterator();
        while (iter.hasNext()) {
            PROPERTY_VALUE val = iter.next();
            builder.append(val.getKey()).append('=').append(val.getValue());
            if (iter.hasNext())
                builder.append(',');
        }
        return builder.toString();

    }

    /**
     * Add a whole address to the given path
     * @param address Other address
     * @see #Address(Address)
     */
    public void add(Address address) {
        if (address!=null && address.path!=null)
            this.path.addAll(address.path);
    }

    /**
     * Indicates if this Address has path elements
     * @return true if the address has no path elements
     */
    @JsonIgnore
    public boolean isEmpty() {
        return path.isEmpty();
    }

    /**
     * Returns the number of path elements of this address
     * @return the number of path elements of this address
     */
    public int size() {
        return path.size();
    }

    /**
     * Returns the n'th path element of the address
     * @param n Number of the wanted path element
     * @return A string representation of the wanted element
     */
    public String get(int n) {
        PROPERTY_VALUE property_value = path.get(n);
        return property_value.getKey() + "=" + property_value.getValue();
    }
}
