/*
 * 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.net.virtual.store.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;
        }
    }
}
