/*
 * Copyright 2015 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.statistic.impl;

import com.google.common.base.Objects;
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.onlab.util.Tools;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.NodeId;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.statistic.FlowStatisticStore;
import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.serializers.KryoSerializer;
import org.slf4j.Logger;

import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.store.statistic.impl.StatisticStoreMessageSubjects.GET_CURRENT;
import static org.onosproject.store.statistic.impl.StatisticStoreMessageSubjects.GET_PREVIOUS;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Maintains flow statistics using RPC calls to collect stats from remote instances
 * on demand.
 */
@Component(immediate = true)
@Service
public class DistributedFlowStatisticStore implements FlowStatisticStore {
    private final Logger log = getLogger(getClass());

    // TODO: Make configurable.
    private static final int MESSAGE_HANDLER_THREAD_POOL_SIZE = 4;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected MastershipService mastershipService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ClusterCommunicationService clusterCommunicator;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ClusterService clusterService;

    private Map<ConnectPoint, Set<FlowEntry>> previous =
            new ConcurrentHashMap<>();

    private Map<ConnectPoint, Set<FlowEntry>> current =
            new ConcurrentHashMap<>();

    protected static final KryoSerializer SERIALIZER = new KryoSerializer() {
        @Override
        protected void setupKryoPool() {
            serializerPool = KryoNamespace.newBuilder()
                    .register(KryoNamespaces.API)
                    .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
                            // register this store specific classes here
                    .build();
        }
    };

    private NodeId local;
    private ExecutorService messageHandlingExecutor;

    private static final long STATISTIC_STORE_TIMEOUT_MILLIS = 3000;

    @Activate
    public void activate() {
        local = clusterService.getLocalNode().id();

        messageHandlingExecutor = Executors.newFixedThreadPool(
                MESSAGE_HANDLER_THREAD_POOL_SIZE,
                groupedThreads("onos/store/statistic", "message-handlers"));

        clusterCommunicator.addSubscriber(
                GET_CURRENT, SERIALIZER::decode, this::getCurrentStatisticInternal, SERIALIZER::encode,
                messageHandlingExecutor);

        clusterCommunicator.addSubscriber(
                GET_CURRENT, SERIALIZER::decode, this::getPreviousStatisticInternal, SERIALIZER::encode,
                messageHandlingExecutor);

        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        clusterCommunicator.removeSubscriber(GET_PREVIOUS);
        clusterCommunicator.removeSubscriber(GET_CURRENT);
        messageHandlingExecutor.shutdown();
        log.info("Stopped");
    }

    @Override
    public synchronized void removeFlowStatistic(FlowRule rule) {
        ConnectPoint cp = buildConnectPoint(rule);
        if (cp == null) {
            return;
        }

        // remove this rule if present from current map
        current.computeIfPresent(cp, (c, e) -> { e.remove(rule); return e;  });

        // remove this on if present from previous map
        previous.computeIfPresent(cp, (c, e) -> { e.remove(rule); return e; });
    }

    @Override
    public synchronized void addFlowStatistic(FlowEntry rule) {
        ConnectPoint cp = buildConnectPoint(rule);
        if (cp == null) {
            return;
        }

        // create one if absent and add this rule
        current.putIfAbsent(cp, new HashSet<>());
        current.computeIfPresent(cp, (c, e) -> { e.add(rule); return e; });

        // remove previous one if present
        previous.computeIfPresent(cp, (c, e) -> { e.remove(rule); return e; });
    }

    public synchronized void updateFlowStatistic(FlowEntry rule) {
        ConnectPoint cp = buildConnectPoint(rule);
        if (cp == null) {
            return;
        }

        Set<FlowEntry> curr = current.get(cp);
        if (curr == null) {
            addFlowStatistic(rule);
        } else {
            Optional<FlowEntry> f = curr.stream().filter(c -> rule.equals(c)).
                    findAny();
            if (f.isPresent() && rule.bytes() < f.get().bytes()) {
                log.debug("DistributedFlowStatisticStore:updateFlowStatistic():" +
                        " Invalid Flow Update! Will be removed!!" +
                        " curr flowId=" + Long.toHexString(rule.id().value()) +
                        ", prev flowId=" + Long.toHexString(f.get().id().value()) +
                        ", curr bytes=" + rule.bytes() + ", prev bytes=" + f.get().bytes() +
                        ", curr life=" + rule.life() + ", prev life=" + f.get().life() +
                        ", curr lastSeen=" + rule.lastSeen() + ", prev lastSeen=" + f.get().lastSeen());
                // something is wrong! invalid flow entry, so delete it
                removeFlowStatistic(rule);
                return;
            }
            Set<FlowEntry> prev = previous.get(cp);
            if (prev == null) {
                prev = new HashSet<>();
                previous.put(cp, prev);
            }

            // previous one is exist
            if (f.isPresent()) {
                // remove old one and add new one
                prev.remove(rule);
                if (!prev.add(f.get())) {
                    log.debug("DistributedFlowStatisticStore:updateFlowStatistic():" +
                                    " flowId={}, add failed into previous.",
                            Long.toHexString(rule.id().value()));
                }
            }

            // remove old one and add new one
            curr.remove(rule);
            if (!curr.add(rule)) {
                log.debug("DistributedFlowStatisticStore:updateFlowStatistic():" +
                                " flowId={}, add failed into current.",
                        Long.toHexString(rule.id().value()));
            }
        }
    }

    @Override
    public Set<FlowEntry> getCurrentFlowStatistic(ConnectPoint connectPoint) {
        final DeviceId deviceId = connectPoint.deviceId();

        NodeId master = mastershipService.getMasterFor(deviceId);
        if (master == null) {
            log.warn("No master for {}", deviceId);
            return Collections.emptySet();
        }

        if (Objects.equal(local, master)) {
            return getCurrentStatisticInternal(connectPoint);
        } else {
            return Tools.futureGetOrElse(clusterCommunicator.sendAndReceive(
                            connectPoint,
                            GET_CURRENT,
                            SERIALIZER::encode,
                            SERIALIZER::decode,
                            master),
                    STATISTIC_STORE_TIMEOUT_MILLIS,
                    TimeUnit.MILLISECONDS,
                    Collections.emptySet());
        }
    }

    private synchronized Set<FlowEntry> getCurrentStatisticInternal(ConnectPoint connectPoint) {
        return current.get(connectPoint);
    }

    @Override
    public Set<FlowEntry> getPreviousFlowStatistic(ConnectPoint connectPoint) {
        final DeviceId deviceId = connectPoint.deviceId();

        NodeId master = mastershipService.getMasterFor(deviceId);
        if (master == null) {
            log.warn("No master for {}", deviceId);
            return Collections.emptySet();
        }

        if (Objects.equal(local, master)) {
            return getPreviousStatisticInternal(connectPoint);
        } else {
            return Tools.futureGetOrElse(clusterCommunicator.sendAndReceive(
                            connectPoint,
                            GET_PREVIOUS,
                            SERIALIZER::encode,
                            SERIALIZER::decode,
                            master),
                    STATISTIC_STORE_TIMEOUT_MILLIS,
                    TimeUnit.MILLISECONDS,
                    Collections.emptySet());
        }
    }

    private synchronized Set<FlowEntry> getPreviousStatisticInternal(ConnectPoint connectPoint) {
        return previous.get(connectPoint);
    }

    private ConnectPoint buildConnectPoint(FlowRule rule) {
        PortNumber port = getOutput(rule);

        if (port == null) {
            return null;
        }
        ConnectPoint cp = new ConnectPoint(rule.deviceId(), port);
        return cp;
    }

    private PortNumber getOutput(FlowRule rule) {
        for (Instruction i : rule.treatment().allInstructions()) {
            if (i.type() == Instruction.Type.OUTPUT) {
                Instructions.OutputInstruction out = (Instructions.OutputInstruction) i;
                return out.port();
            }
            if (i.type() == Instruction.Type.DROP) {
                return PortNumber.P0;
            }
        }
        return null;
    }
}