/**
 * Copyright © CENRA (2016)
 *
 * remi.clement@espaces-naturels.fr
 * 
 * This software is a multi-platform and portable application based on 
 * the scientifical toolbox to monitor wetlands. With this toolbox it’s 
 * possible to calculate indicators «RhoMéO» to monitor quality, 
 * fonctionalities and urban and agricultural pressures of wetlands. 
 * Indicators are calculated using naturalist data entered and/or imported,
 * and geographic data downloaded from a geographic server.
 * 
 * This software is governed by the CeCILL license under French law and
 * abiding by the rules of distribution of free software.  You can  use, 
 * modify and/ or redistribute the software under the terms of the CeCILL
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info". 
 * 
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability. 
 * 
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or 
 * data to be ensured and,  more generally, to use and operate it in the 
 * same conditions as regards security. 
 * 
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL license and that you accept its terms.
*/
package fr.cenra.rhomeo.api.result;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleObjectProperty;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * An utility class to map association between instances from a given base
 * class and some indexed numeric values.
 *
 * The equality of two {@link IndexMapper} is based ont the equality of their
 * included "key" instances.
 *
 * @param <C> The type of the base class.
 *
 * @author Samuel Andrés (Geomatys)
 * @author Cédric Briançon (Geomatys)
 */
public class IndexMapper<C> {

    private final ObjectProperty<C> keyProperty = new SimpleObjectProperty<>();

    private final Map<String, ObjectProperty<Number>> map = new HashMap<>();

    /**
     *
     * @param key
     */
    public IndexMapper(final C key){
        this.keyProperty.set(key);
    }

    public C getKey(){return keyProperty.get();}

    public ReadOnlyObjectProperty<C> keyProperty(){return keyProperty;}

    public ReadOnlyObjectProperty valueProperty(final String k){return map.get(k);}

    public void setValue(final String k, final Number v){
        if(valueProperty(k)==null){
            map.put(k, new SimpleObjectProperty<>());
        }
        map.get(k).set(v);
    }

    public Collection<ObjectProperty<Number>> getValues() {
        return map.values();
    }
    
    public Set<String> getValueAccessors(){
        return map.keySet();
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 97 * hash + Objects.hashCode(this.keyProperty);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final IndexMapper<?> other = (IndexMapper<?>) obj;
        if (!Objects.equals(this.keyProperty, other.keyProperty)) {
            return false;
        }
        return true;
    }
}
