/*
 * Copyright 2015 Open Networking Laboratory
 *
 * Licensed 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.onosproject.ui.topo;

import com.google.common.collect.Sets;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Models a panel displayed on the Topology View.
 */
public class PropertyPanel {

    private static final NumberFormat NF = NumberFormat.getInstance();

    private String title;
    private String typeId;
    private String id;
    private List<Prop> properties = new ArrayList<>();
    private List<ButtonId> buttons = new ArrayList<>();

    /**
     * Constructs a property panel model with the given title and
     * type identifier (icon to display).
     *
     * @param title title text
     * @param typeId type (icon) ID
     */
    public PropertyPanel(String title, String typeId) {
        this.title = title;
        this.typeId = typeId;
    }

    /**
     * Returns a number formatter to use for formatting integer and long
     * property values.
     * <p>
     * This default implementation uses a formatter for the default
     * locale. For example:
     * <pre>
     *     Locale.ENGLISH  :  1000 -&gt; "1,000"
     *     Locale.FRENCH   :  1000 -&gt; "1 000"
     *     Locale.GERMAN   :  1000 -&gt; "1.000"
     * </pre>
     *
     * @return the number formatter
     */
    protected NumberFormat formatter() {
        return NF;
    }

    /**
     * Adds an ID field to the panel data, to be included in
     * the returned JSON data to the client.
     *
     * @param id the identifier
     * @return self, for chaining
     */
    public PropertyPanel id(String id) {
        this.id = id;
        return this;
    }

    /**
     * Adds a property to the panel data.
     *
     * @param key property key
     * @param value property value
     * @return self, for chaining
     */
    public PropertyPanel addProp(String key, String value) {
        properties.add(new Prop(key, value));
        return this;
    }

    /**
     * Adds a property to the panel data, using a decimal formatter.
     *
     * @param key property key
     * @param value property value
     * @return self, for chaining
     */
    public PropertyPanel addProp(String key, int value) {
        properties.add(new Prop(key, formatter().format(value)));
        return this;
    }

    /**
     * Adds a property to the panel data, using a decimal formatter.
     *
     * @param key property key
     * @param value property value
     * @return self, for chaining
     */
    public PropertyPanel addProp(String key, long value) {
        properties.add(new Prop(key, formatter().format(value)));
        return this;
    }

    /**
     * Adds a property to the panel data. Note that the value's
     * {@link Object#toString toString()} method is used to convert the
     * value to a string.
     *
     * @param key property key
     * @param value property value
     * @return self, for chaining
     */
    public PropertyPanel addProp(String key, Object value) {
        properties.add(new Prop(key, value.toString()));
        return this;
    }

    /**
     * Adds a property to the panel data. Note that the value's
     * {@link Object#toString toString()} method is used to convert the
     * value to a string, from which the characters defined in the given
     * regular expression string are stripped.
     *
     * @param key property key
     * @param value property value
     * @param reStrip regexp characters to strip from value string
     * @return self, for chaining
     */
    public PropertyPanel addProp(String key, Object value, String reStrip) {
        String val = value.toString().replaceAll(reStrip, "");
        properties.add(new Prop(key, val));
        return this;
    }

    /**
     * Adds a separator to the panel data.
     *
     * @return self, for chaining
     */
    public PropertyPanel addSeparator() {
        properties.add(new Separator());
        return this;
    }

    /**
     * Returns the title text.
     *
     * @return title text
     */
    public String title() {
        return title;
    }

    /**
     * Returns the type identifier.
     *
     * @return type identifier
     */
    public String typeId() {
        return typeId;
    }

    /**
     * Returns the internal ID.
     *
     * @return the ID
     */
    public String id() {
        return id;
    }

    /**
     * Returns the list of properties to be displayed.
     *
     * @return the property list
     */
    // TODO: consider protecting this?
    public List<Prop> properties() {
        return properties;
    }

    /**
     * Returns the list of button descriptors.
     *
     * @return the button list
     */
    // TODO: consider protecting this?
    public List<ButtonId> buttons() {
        return buttons;
    }

    // == MUTATORS

    /**
     * Sets the title text.
     *
     * @param title title text
     * @return self, for chaining
     */
    public PropertyPanel title(String title) {
        this.title = title;
        return this;
    }

    /**
     * Sets the type identifier (icon ID).
     *
     * @param typeId type identifier
     * @return self, for chaining
     */
    public PropertyPanel typeId(String typeId) {
        this.typeId = typeId;
        return this;
    }

    /**
     * Removes properties with the given keys from the list.
     *
     * @param keys keys of properties to remove
     * @return self, for chaining
     */
    public PropertyPanel removeProps(String... keys) {
        Set<String> forRemoval = Sets.newHashSet(keys);
        List<Prop> toKeep = new ArrayList<>();
        for (Prop p: properties) {
            if (!forRemoval.contains(p.key())) {
                toKeep.add(p);
            }
        }
        properties = toKeep;
        return this;
    }

    /**
     * Removes all currently defined properties.
     *
     * @return self, for chaining
     */
    public PropertyPanel removeAllProps() {
        properties.clear();
        return this;
    }

    /**
     * Adds the given button descriptor to the panel data.
     *
     * @param button button descriptor
     * @return self, for chaining
     */
    public PropertyPanel addButton(ButtonId button) {
        buttons.add(button);
        return this;
    }

    /**
     * Removes buttons with the given descriptors from the list.
     *
     * @param descriptors descriptors to remove
     * @return self, for chaining
     */
    public PropertyPanel removeButtons(ButtonId... descriptors) {
        Set<ButtonId> forRemoval = Sets.newHashSet(descriptors);
        List<ButtonId> toKeep = new ArrayList<>();
        for (ButtonId bd: buttons) {
            if (!forRemoval.contains(bd)) {
                toKeep.add(bd);
            }
        }
        buttons = toKeep;
        return this;
    }

    /**
     * Removes all currently defined buttons.
     *
     * @return self, for chaining
     */
    public PropertyPanel removeAllButtons() {
        buttons.clear();
        return this;
    }

    // ====================


    /**
     * Simple data carrier for a property, composed of a key/value pair.
     */
    public static class Prop {
        private final String key;
        private final String value;

        /**
         * Constructs a property data value.
         *
         * @param key property key
         * @param value property value
         */
        public Prop(String key, String value) {
            this.key = key;
            this.value = value;
        }

        /**
         * Returns the property's key.
         *
         * @return the key
         */
        public String key() {
            return key;
        }

        /**
         * Returns the property's value.
         *
         * @return the value
         */
        public String value() {
            return value;
        }

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

            Prop prop = (Prop) o;
            return key.equals(prop.key) && value.equals(prop.value);
        }

        @Override
        public int hashCode() {
            int result = key.hashCode();
            result = 31 * result + value.hashCode();
            return result;
        }

        @Override
        public String toString() {
            return "{" + key + " -> " + value + "}";
        }
    }

    /**
     * Auxiliary class representing a separator property.
     */
    public static class Separator extends Prop {
        public Separator() {
            super("-", "");
        }
    }

}
