package net.ranides.assira.observable;

import net.ranides.assira.collection.maps.OpenMultiMap;
import net.ranides.assira.collection.prototype.GenericKey;
import net.ranides.assira.collection.prototype.GenericMap;
import net.ranides.assira.collection.prototype.OpenGenericMap;
import net.ranides.assira.collection.utils.HashCollection;
import net.ranides.assira.events.EventListener;
import net.ranides.assira.events.EventRouter;

import java.util.Map;

public class ObservableGenericMap<K> extends OpenGenericMap<K> {

    private final EventRouter router;

    public ObservableGenericMap(EventRouter router) {
        this(router, HashCollection.INITIAL_SIZE, HashCollection.LOAD_FACTOR);
    }

    public ObservableGenericMap(EventRouter router, int capacity) {
        this(router, capacity, HashCollection.LOAD_FACTOR);
    }

    public ObservableGenericMap(EventRouter router, int capacity, float factor) {
        super(true);
        this.router = router;
        this.map = new ObservableContent(router, new OpenMultiMap<>(capacity, factor));
    }

    public EventRouter router() {
        return router;
    }

    public <E extends GenericMapEvent<K>> void addEventListener(Class<E> event, EventListener<? super E> listener) {
        router.addEventListener(event, listener);
    }

    private final class ObservableContent extends ObservableMap<GenericKey<K,?>, Object> {

        public ObservableContent(EventRouter router, Map<GenericKey<K, ?>, Object> map) {
            super(router, map);
        }

        @Override
        protected void signalRemove(GenericKey<K, ?> key, Object prev) {
            router.signalEvent(new GenericMapEvent.Remove<>(ObservableGenericMap.this, key, prev));
        }

        @Override
        protected void signalClear() {
            router.signalEvent(new GenericMapEvent.Clear<>(ObservableGenericMap.this));
        }

        @Override
        protected void signalPut(GenericKey<K, ?> key, Object prev, Object value) {
            router.signalEvent(new GenericMapEvent.Put<>(ObservableGenericMap.this, key, prev, value));
        }

        @Override
        protected void signalPutAll(Map<? extends GenericKey<K, ?>, ?> m) {
            router.signalEvent(new GenericMapEvent.PutAll<>(ObservableGenericMap.this, GenericMap.wrap((Map)m)) );
        }

    }

}
