/*
 *  @author Ranides Atterwim <ranides@gmail.com>
 *  @copyright Ranides Atterwim
 *  @license WTFPL
 *  @url http://ranides.net/projects/assira
 */

package net.ranides.assira.config;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import net.ranides.assira.events.Event;
import net.ranides.assira.events.EventBinding;
import net.ranides.assira.events.EventListener;
import net.ranides.assira.events.EventRouter;
import net.ranides.assira.events.EventDispatcher;

/**
 *
 * @author ranides
 */
@SuppressWarnings({
    "SIC_INNER_SHOULD_BE_STATIC_ANON"
})
public abstract class AbstractConfiguration extends AbstractBranch implements Configuration {

    protected final EventRouter dispatcher;

    /**
     * Pełna ścieżka podana podczas tworzenia konfiguracji
     */
    protected final String resource;
    /**
     * Rodzaj podanej ścieżki: "file" lub "url". W przypadku ścieżki nie określającej
     * protokołu przyjmowany jest typ "file". W przypadku adresu URL konieczne jest
     * podanie najpierw protokołu "url:" a następnie pełnego adresu, włącznie z
     * konkretnym prefiksem określającym rodzaj transportu (np "http:", "ftp:", ...).
     */
    protected final String protocol;
    /**
     * Część pozostała po usunięciu rodzaju ze ścieżki rodzaju.
     */
    protected final String location;

    /**
     * Pamięć podręczna na przechowywane wartości konfiguracyjne.
     */
    protected Map<String, Object> values;

    /**
     * <p>
     * Tworzy nową konfigurację powiązaną z zasobem wskazywanym przez ścieżkę.
     * Konfiguracja może być ładowana i zapisywana z/do plików lokalnych.
     * Może też być ładowana w trybie tylko-do-odczytu z zewnętrznego źródła
     * określonego za pomocą URL.
     * </p>
     * <pre>
     *   {@code
     *   "/user/home/config.json"
     *   "file:/user/home/config.json"
     *   "file:d:/app/config.json"
     *   "url:http://example.com/config.json"
     * }</pre>
     * @param path
     */
    public AbstractConfiguration(String path) {
        this.dispatcher = new EventDispatcher();
        this.values = new HashMap<>();
        this.resource = path;

        String[] params = path.split(":",2);
        if(params.length == 2) {
            protocol = (params.length == 2) ? params[0] : "file";
            location = params[1];
        } else {
            protocol = "file";
            location = params[0];
        }
    }

    @Override
    public String resource() {
        return resource;
    }

    @Override
    public Map<String,Object> asMap() {
        return values;
    }

    @Override
    public Object get(String path, Object ddefault) throws ConfigException {
        return get(values, path, ddefault);
    }

    @Override
    public void put(String path, Object value) throws ConfigException {
        put(values, path, value);
    }


/* ************************************************************************** */


    @Override
    public <T extends Event> void addEventListener(Class<T> event, EventListener<? super T> listener) {
        dispatcher.addEventListener(event, listener);
    }

    @Override
    public <T extends Event> void removeEventListener(Class<T> event, EventListener<? super T> listener) {
        dispatcher.removeEventListener(event, listener);
    }

    @Override
    public void removeAllEventListeners() {
        dispatcher.removeAllEventListeners();
    }

    @Override
    public Collection<EventBinding<?>> getEventListeners() {
        return dispatcher.getEventListeners();
    }

    @Override
    public boolean signalEvent(Event event) {
        return dispatcher.signalEvent(event);
    }

    @Override
    public void dispose() {
        dispatcher.dispose();
    }

    @Override
    public void handleEvent(Event event) {
        dispatcher.handleEvent(event);
    }

    @Override
    public int getEventListenersCount() {
        return dispatcher.getEventListenersCount();
    }

}
