/*
 * Copyright 2015-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.store.flowobjective.impl;

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.onlab.util.KryoNamespace;
import org.onosproject.net.behaviour.DefaultNextGroup;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.flowobjective.FlowObjectiveStore;
import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
import org.onosproject.net.flowobjective.ObjectiveEvent;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.service.AtomicCounter;
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.onosproject.store.service.Versioned;
import org.slf4j.Logger;

import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * Manages the inventory of created next groups.
 */
@Component(immediate = true, enabled = true)
@Service
public class DistributedFlowObjectiveStore
        extends AbstractStore<ObjectiveEvent, FlowObjectiveStoreDelegate>
        implements FlowObjectiveStore {

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

    private ConsistentMap<Integer, byte[]> nextGroups;

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

    private AtomicCounter nextIds;
    private MapEventListener<Integer, byte[]> mapListener = new NextGroupListener();
    // event queue to separate map-listener threads from event-handler threads (tpool)
    private BlockingQueue<ObjectiveEvent> eventQ;
    private ExecutorService tpool;

    @Activate
    public void activate() {
        tpool = Executors.newFixedThreadPool(4, groupedThreads("onos/flobj-notifier", "%d", log));
        eventQ = new LinkedBlockingQueue<ObjectiveEvent>();
        tpool.execute(new FlowObjectiveNotifier());
        nextGroups = storageService.<Integer, byte[]>consistentMapBuilder()
                .withName("flowobjective-groups")
                .withSerializer(Serializer.using(
                        new KryoNamespace.Builder()
                                .register(byte[].class)
                                .register(Versioned.class)
                                .build("DistributedFlowObjectiveStore")))
                .build();
        nextGroups.addListener(mapListener);
        nextIds = storageService.getAtomicCounter("next-objective-counter");
        log.info("Started");
    }


    @Deactivate
    public void deactivate() {
        tpool.shutdown();
        log.info("Stopped");
    }

    @Override
    public void putNextGroup(Integer nextId, NextGroup group) {
        nextGroups.put(nextId, group.data());
        notifyDelegate(new ObjectiveEvent(ObjectiveEvent.Type.ADD, nextId));
    }

    @Override
    public NextGroup getNextGroup(Integer nextId) {
        Versioned<byte[]> versionGroup = nextGroups.get(nextId);
        if (versionGroup != null) {
            return new DefaultNextGroup(versionGroup.value());
        }
        return null;
    }

    @Override
    public NextGroup removeNextGroup(Integer nextId) {
        Versioned<byte[]> versionGroup = nextGroups.remove(nextId);
        if (versionGroup != null) {
            notifyDelegate(new ObjectiveEvent(ObjectiveEvent.Type.REMOVE, nextId));
            return new DefaultNextGroup(versionGroup.value());
        }
        return null;
    }

    @Override
    public Map<Integer, NextGroup> getAllGroups() {
        Map<Integer, NextGroup> nextGroupMappings = new HashMap<>();
        for (int key : nextGroups.keySet()) {
            NextGroup nextGroup = getNextGroup(key);
            if (nextGroup != null) {
                nextGroupMappings.put(key, nextGroup);
            }
        }
        return nextGroupMappings;
    }

    @Override
    public int allocateNextId() {
        return (int) nextIds.incrementAndGet();
    }

    private class FlowObjectiveNotifier implements Runnable {
        @Override
        public void run() {
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    notifyDelegate(eventQ.take());
                }
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    }

    private class NextGroupListener implements MapEventListener<Integer, byte[]> {
        @Override
        public void event(MapEvent<Integer, byte[]> event) {
            switch (event.type()) {
            case INSERT:
                eventQ.add(new ObjectiveEvent(ObjectiveEvent.Type.ADD, event.key()));
                break;
            case REMOVE:
                eventQ.add(new ObjectiveEvent(ObjectiveEvent.Type.REMOVE, event.key()));
                break;
            case UPDATE:
                // TODO Introduce UPDATE ObjectiveEvent when the map is being updated
                break;
            default:
                break;
            }
        }
    }

}
