package net.ranides.assira.observable;

import net.ranides.assira.collection.maps.OpenMap;
import net.ranides.assira.collection.prototype.PrototypeMap;
import net.ranides.assira.events.EventListener;
import net.ranides.assira.events.EventRouter;

import java.util.Map;

public class ObservablePrototypeMap extends PrototypeMap {

    private final EventRouter router;

    public ObservablePrototypeMap(EventRouter router) {
        this(true, router, null, new OpenMap<>());
    }

    public ObservablePrototypeMap(EventRouter router, PrototypeMap parent) {
        this(true, router, parent, new OpenMap<>());
    }

    public ObservablePrototypeMap(EventRouter router, Map<Object, ?> content) {
        this(true, router, null, new OpenMap<>(content));
    }

    public ObservablePrototypeMap(EventRouter router, PrototypeMap parent, Map<Object, ?> content) {
        this(true, router, parent, new OpenMap<>(content));
    }

    private ObservablePrototypeMap(boolean direct, EventRouter router, PrototypeMap parent, Map<Object, Object> content) {
        super(true);
        this.parent = parent;
        this.declared = new ObservableContent(router, content);
        this.router = router;
    }

    public EventRouter router() {
        return router;
    }

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

    private final class ObservableContent extends ObservableMap<Object, Object> {

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

        @Override
        protected void signalRemove(Object key, Object prev) {
            router.signalEvent(new MapEvent.Remove<>(ObservablePrototypeMap.this, key, prev));
        }

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

        @Override
        protected void signalPut(Object key, Object prev, Object value) {
            router.signalEvent(new MapEvent.Put<>(ObservablePrototypeMap.this, key, prev, value));
        }

        @Override
        protected void signalPutAll(Map<? extends Object, ?> m) {
            router.signalEvent(new MapEvent.PutAll<>(ObservablePrototypeMap.this, m) );
        }

    }

}
