/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.incubator.store.virtual.impl;

import com.google.common.collect.Maps;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.VirtualNetworkFlowObjectiveStore;
import org.onosproject.net.behaviour.DefaultNextGroup;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
import org.onosproject.net.flowobjective.ObjectiveEvent;
import org.onosproject.store.service.AtomicCounter;
import org.onosproject.store.service.StorageService;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;

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

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

/**
 * Single instance implementation of store to manage
 * the inventory of created next groups for virtual network.
 */
@Component(immediate = true, service = VirtualNetworkFlowObjectiveStore.class)
public class SimpleVirtualFlowObjectiveStore
        extends AbstractVirtualStore<ObjectiveEvent, FlowObjectiveStoreDelegate>
        implements VirtualNetworkFlowObjectiveStore {

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

    private ConcurrentMap<NetworkId, ConcurrentMap<Integer, byte[]>> nextGroupsMap;

    private AtomicCounter nextIds;

    // event queue to separate map-listener threads from event-handler threads (tpool)
    private BlockingQueue<VirtualObjectiveEvent> eventQ;
    private ExecutorService tpool;

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

    @Activate
    public void activate() {
        tpool = Executors.newFixedThreadPool(4, groupedThreads("onos/virtual/flobj-notifier", "%d", log));
        eventQ = new LinkedBlockingQueue<>();
        tpool.execute(new FlowObjectiveNotifier());

        initNextGroupsMap();

        nextIds = storageService.getAtomicCounter("next-objective-counter");
        log.info("Started");
    }

    public void deactivate() {
        log.info("Stopped");
    }

    protected void initNextGroupsMap() {
        nextGroupsMap = Maps.newConcurrentMap();
    }

    protected void updateNextGroupsMap(NetworkId networkId,
                                       ConcurrentMap<Integer, byte[]> nextGroups) {
    }

    protected ConcurrentMap<Integer, byte[]> getNextGroups(NetworkId networkId) {
        nextGroupsMap.computeIfAbsent(networkId, n -> Maps.newConcurrentMap());
        return nextGroupsMap.get(networkId);
    }

    @Override
    public void putNextGroup(NetworkId networkId, Integer nextId, NextGroup group) {
        ConcurrentMap<Integer, byte[]> nextGroups = getNextGroups(networkId);
        nextGroups.put(nextId, group.data());
        updateNextGroupsMap(networkId, nextGroups);

        eventQ.add(new VirtualObjectiveEvent(networkId, ObjectiveEvent.Type.ADD, nextId));
    }

    @Override
    public NextGroup getNextGroup(NetworkId networkId, Integer nextId) {
        ConcurrentMap<Integer, byte[]> nextGroups = getNextGroups(networkId);
        byte[] groupData = nextGroups.get(nextId);
        if (groupData != null) {
            return new DefaultNextGroup(groupData);
        }
        return null;
    }

    @Override
    public NextGroup removeNextGroup(NetworkId networkId, Integer nextId) {
        ConcurrentMap<Integer, byte[]> nextGroups = getNextGroups(networkId);
        byte[] nextGroup = nextGroups.remove(nextId);
        updateNextGroupsMap(networkId, nextGroups);

        eventQ.add(new VirtualObjectiveEvent(networkId, ObjectiveEvent.Type.REMOVE, nextId));

        return new DefaultNextGroup(nextGroup);
    }

    @Override
    public Map<Integer, NextGroup> getAllGroups(NetworkId networkId) {
        ConcurrentMap<Integer, byte[]> nextGroups = getNextGroups(networkId);

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

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

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

    private class VirtualObjectiveEvent extends ObjectiveEvent {
        NetworkId networkId;

        public VirtualObjectiveEvent(NetworkId networkId, Type type,
                                     Integer objective) {
            super(type, objective);
            this.networkId = networkId;
        }

        NetworkId networkId() {
            return networkId;
        }
    }
}
