/*
 * Copyright 2017-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.mapping.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.mapping.DefaultMapping;
import org.onosproject.mapping.DefaultMappingEntry;
import org.onosproject.mapping.Mapping;
import org.onosproject.mapping.MappingEntry;
import org.onosproject.mapping.MappingEvent;
import org.onosproject.mapping.MappingId;
import org.onosproject.mapping.MappingKey;
import org.onosproject.mapping.MappingStore;
import org.onosproject.mapping.MappingStoreDelegate;
import org.onosproject.mapping.MappingTreatment;
import org.onosproject.mapping.MappingValue;
import org.onosproject.mapping.actions.MappingAction;
import org.onosproject.mapping.addresses.MappingAddress;
import org.onosproject.mapping.instructions.MappingInstruction;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.MapEvent;
import org.onosproject.store.service.MapEventListener;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.slf4j.Logger;

import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Implementation of a distributed store for managing mapping information.
 */
@Component(immediate = true)
@Service
public class DistributedMappingStore
        extends AbstractStore<MappingEvent, MappingStoreDelegate>
        implements MappingStore {

    private final Logger log = getLogger(getClass());

    private ConsistentMap<MappingId, Mapping> database;
    private ConsistentMap<MappingId, Mapping> cache;

    private Map<MappingId, Mapping> databaseMap;
    private Map<MappingId, Mapping> cacheMap;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected StorageService storageService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    private final MapEventListener<MappingId, Mapping> listener = new InternalListener();

    @Activate
    public void activate() {

        Serializer serializer = Serializer.using(KryoNamespaces.API,
                                                    Mapping.class,
                                                    DefaultMapping.class,
                                                    MappingId.class,
                                                    MappingEvent.Type.class,
                                                    MappingKey.class,
                                                    MappingValue.class,
                                                    MappingAddress.class,
                                                    MappingAddress.Type.class,
                                                    MappingAction.class,
                                                    MappingAction.Type.class,
                                                    MappingTreatment.class,
                                                    MappingInstruction.class,
                                                    MappingInstruction.Type.class);

        database = storageService.<MappingId, Mapping>consistentMapBuilder()
                        .withName("onos-mapping-database")
                        .withSerializer(serializer)
                        .build();

        cache = storageService.<MappingId, Mapping>consistentMapBuilder()
                        .withName("onos-mapping-cache")
                        .withSerializer(serializer)
                        .build();

        database.addListener(listener);
        cache.addListener(listener);
        databaseMap = database.asJavaMap();
        cacheMap = cache.asJavaMap();
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        database.removeListener(listener);
        cache.removeListener(listener);
        log.info("Stopped");
    }

    /**
     * Obtains map representation of mapping store.
     *
     * @param type mapping store type
     * @return map representation of mapping store
     */
    private Map<MappingId, Mapping> getStoreMap(Type type) {
        switch (type) {
            case MAP_DATABASE:
                return databaseMap;
            case MAP_CACHE:
                return cacheMap;
            default:
                log.warn("Unrecognized map store type {}", type);
                return Maps.newConcurrentMap();
        }
    }

    /**
     * Obtains mapping store.
     *
     * @param type mapping store type
     * @return mapping store
     */
    private ConsistentMap<MappingId, Mapping> getStore(Type type) {
        switch (type) {
            case MAP_DATABASE:
                return database;
            case MAP_CACHE:
                return cache;
            default:
                throw new IllegalArgumentException("Wrong mapping store " + type);
        }
    }

    @Override
    public int getMappingCount(Type type) {
        AtomicInteger sum = new AtomicInteger(0);
        deviceService.getDevices().forEach(device ->
                sum.addAndGet(Iterables.size(getMappingEntries(type, device.id()))));
        return sum.get();
    }

    @Override
    public MappingEntry getMappingEntry(Type type, Mapping mapping) {

        return new DefaultMappingEntry(getStoreMap(type).get(mapping.id()));
    }

    @Override
    public Iterable<MappingEntry> getMappingEntries(Type type, DeviceId deviceId) {

        Map<MappingId, Mapping> storeMap = getStoreMap(type);
        return ImmutableList.copyOf(storeMap.values().stream()
                                             .filter(m -> m.deviceId() == deviceId)
                                             .map(DefaultMappingEntry::new)
                                             .collect(Collectors.toList()));
    }

    @Override
    public void storeMapping(Type type, Mapping mapping) {

        getStore(type).put(mapping.id(), mapping);
    }

    @Override
    public MappingEvent removeMapping(Type type, Mapping mapping) {

        getStore(type).remove(mapping.id());
        return null;
    }

    @Override
    public void pendingDeleteMapping(Type type, Mapping mapping) {
        // TODO: this will be implemented when management plane is ready
        log.error("This method will be available when management plane is ready");
    }

    @Override
    public MappingEvent addOrUpdateMappingEntry(Type type, MappingEntry entry) {
        // TODO: this will be implemented when management plane is ready
        log.error("This method will be available when management plane is ready");
        return null;
    }

    @Override
    public MappingEvent pendingMappingEntry(Type type, MappingEntry entry) {
        // TODO: this will be implemented when management plane is ready
        log.error("This method will be available when management plane is ready");
        return null;
    }

    @Override
    public void purgeMappingEntries(Type type) {
        getStore(type).clear();
    }

    /**
     * Event listener to notify delegates about mapping events.
     */
    private class InternalListener implements MapEventListener<MappingId, Mapping> {

        @Override
        public void event(MapEvent<MappingId, Mapping> event) {
            final MappingEvent.Type type;
            final Mapping mapping;

            switch (event.type()) {
                case INSERT:
                    type = MappingEvent.Type.MAPPING_ADDED;
                    mapping = event.newValue().value();
                    break;
                case UPDATE:
                    type = MappingEvent.Type.MAPPING_UPDATED;
                    mapping = event.newValue().value();
                    break;
                case REMOVE:
                    type = MappingEvent.Type.MAPPING_REMOVED;
                    mapping = event.oldValue().value();
                    break;
                default:
                    throw new IllegalArgumentException("Wrong event type " + event.type());
            }
            notifyDelegate(new MappingEvent(type, mapping));
        }
    }
}
