package com.vladsch.flexmark.util.options;

import com.vladsch.flexmark.util.collection.DataValueFactory;

public interface MutableDataHolder extends DataHolder, MutableDataSetter {
    /**
     * Get the given key, if it does not exist then use the key's factory to create a new value and put it into the collection
     * so that the following get of the same key will find a value
     *
     * @param key data key
     * @return return stored value or newly created value
     */
    @Override
    <T> T get(DataKey<T> key);

    /**
     * Store the given value for the key
     *
     * @param <T>  data type of the data referred by the key
     * @param key   data key
     * @param value value to store
     * @return mutable data holder for chained calls
     */
    <T> MutableDataHolder set(DataKey<T> key, T value);

    /**
     * Remove the stored value for the key, used to force to default or to force recompute
     *
     * @param <T>  data type of the data referred by the key
     * @param key   data key to remove
     * @return mutable data holder for chained calls
     */
    <T> MutableDataHolder remove(DataKey<T> key);

    /**
     * Store the given value for the key
     *
     * @param dataSetter   data setter which will set values
     * @return mutable data holder for chained calls
     */
    MutableDataHolder setFrom(MutableDataSetter dataSetter);

    /**
     * Copy all values from one data holder to this data holder
     *
     * @param other data holder from which to copy all values
     * @return mutable data holder for chained calls
     */
    MutableDataHolder setAll(DataHolder other);

    /**
     * Set options in gven mutable data hoer
     *
     * @param dataHolder data holder where to copy options from this data holder
     * @return dataHolder
     */
    @Override
    MutableDataHolder setIn(MutableDataHolder dataHolder);

    /**
     * Will return the value previously set or generate a new value using the given factory.
     *
     * NOTE: if a new value is generated it will be stored for the given key so that subsequent calls with the same parameters will return the same value as the first call that generated the new value.
     *
     * @param key data key identifying the data
     * @param factory data value factory to use if the data referred by the key is not set
     * @param <T>  data type of the data referred by the key
     * @return  data stored for the key or a value generated by the value factory.
     */
    <T> T getOrCompute(DataKey<T> key, DataValueFactory<T> factory);

    /**
     * clear all options out of the data set
     * @return mutable data holder for chained calls
     */
    MutableDataHolder clear();
}
