/*
 * Copyright 2014-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.store.cluster.impl;

import com.google.common.collect.ImmutableSet;
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.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.IpAddress;
import org.onlab.util.KryoNamespace;
import org.onosproject.cfg.ConfigProperty;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.cluster.ClusterEvent;
import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ClusterStore;
import org.onosproject.cluster.ClusterStoreDelegate;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.ControllerNode.State;
import org.onosproject.cluster.DefaultControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.core.Version;
import org.onosproject.core.VersionService;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.cluster.messaging.Endpoint;
import org.onosproject.store.cluster.messaging.MessagingService;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.Serializer;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;

import java.time.Instant;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ACTIVATED;
import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_DEACTIVATED;
import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_READY;
import static org.slf4j.LoggerFactory.getLogger;

@Component(immediate = true)
@Service
/**
 * Distributed cluster nodes store that employs an accrual failure
 * detector to identify cluster member up/down status.
 */
public class DistributedClusterStore
        extends AbstractStore<ClusterEvent, ClusterStoreDelegate>
        implements ClusterStore {

    private static final Logger log = getLogger(DistributedClusterStore.class);

    public static final String HEARTBEAT_MESSAGE = "onos-cluster-heartbeat";

    private static final int DEFAULT_HEARTBEAT_INTERVAL = 100;
    @Property(name = "heartbeatInterval", intValue = DEFAULT_HEARTBEAT_INTERVAL,
            label = "Interval time to send heartbeat to other controller nodes (millisecond)")
    private int heartbeatInterval = DEFAULT_HEARTBEAT_INTERVAL;

    private static final int DEFAULT_PHI_FAILURE_THRESHOLD = 10;
    @Property(name = "phiFailureThreshold", intValue = DEFAULT_PHI_FAILURE_THRESHOLD,
            label = "the value of Phi threshold to detect accrual failure")
    private int phiFailureThreshold = DEFAULT_PHI_FAILURE_THRESHOLD;

    private static final Serializer SERIALIZER = Serializer.using(
            KryoNamespace.newBuilder()
                    .register(KryoNamespaces.API)
                    .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
                    .register(HeartbeatMessage.class)
                    .build("ClusterStore"));

    private static final String INSTANCE_ID_NULL = "Instance ID cannot be null";

    private final Map<NodeId, ControllerNode> allNodes = Maps.newConcurrentMap();
    private final Map<NodeId, State> nodeStates = Maps.newConcurrentMap();
    private final Map<NodeId, Version> nodeVersions = Maps.newConcurrentMap();
    private final Map<NodeId, Instant> nodeLastUpdatedTimes = Maps.newConcurrentMap();

    private ScheduledExecutorService heartBeatSender = Executors.newSingleThreadScheduledExecutor(
            groupedThreads("onos/cluster/membership", "heartbeat-sender", log));
    private ExecutorService heartBeatMessageHandler = Executors.newSingleThreadExecutor(
            groupedThreads("onos/cluster/membership", "heartbeat-receiver", log));

    private PhiAccrualFailureDetector failureDetector;

    private ControllerNode localNode;
    private Version localVersion;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected VersionService versionService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ClusterMetadataService clusterMetadataService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected MessagingService messagingService;

    // This must be optional to avoid a cyclic dependency
    @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY,
            bind = "bindComponentConfigService",
            unbind = "unbindComponentConfigService",
            policy = ReferencePolicy.DYNAMIC)
    protected ComponentConfigService cfgService;

    /**
     * Hook for wiring up optional reference to a service.
     *
     * @param service service being announced
     */
    protected void bindComponentConfigService(ComponentConfigService service) {
        if (cfgService == null) {
            cfgService = service;
            cfgService.registerProperties(getClass());
            readComponentConfiguration();
        }
    }

    /**
     * Hook for unwiring optional reference to a service.
     *
     * @param service service being withdrawn
     */
    protected void unbindComponentConfigService(ComponentConfigService service) {
        if (cfgService == service) {
            cfgService.unregisterProperties(getClass(), false);
            cfgService = null;
        }
    }

    @Activate
    public void activate() {
        localNode = clusterMetadataService.getLocalNode();
        localVersion = versionService.version();
        nodeVersions.put(localNode.id(), localVersion);

        messagingService.registerHandler(HEARTBEAT_MESSAGE,
                new HeartbeatMessageHandler(), heartBeatMessageHandler);

        failureDetector = new PhiAccrualFailureDetector();

        heartBeatSender.scheduleWithFixedDelay(this::heartbeat, 0,
                heartbeatInterval, TimeUnit.MILLISECONDS);

        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        messagingService.unregisterHandler(HEARTBEAT_MESSAGE);
        heartBeatSender.shutdownNow();
        heartBeatMessageHandler.shutdownNow();

        log.info("Stopped");
    }

    @Modified
    public void modified(ComponentContext context) {
        readComponentConfiguration();
    }

    @Override
    public void setDelegate(ClusterStoreDelegate delegate) {
        checkNotNull(delegate, "Delegate cannot be null");
        this.delegate = delegate;
    }

    @Override
    public void unsetDelegate(ClusterStoreDelegate delegate) {
        this.delegate = null;
    }

    @Override
    public boolean hasDelegate() {
        return this.delegate != null;
    }

    @Override
    public ControllerNode getLocalNode() {
        return localNode;
    }

    @Override
    public Set<ControllerNode> getNodes() {
        return ImmutableSet.copyOf(allNodes.values());
    }

    @Override
    public ControllerNode getNode(NodeId nodeId) {
        checkNotNull(nodeId, INSTANCE_ID_NULL);
        return allNodes.get(nodeId);
    }

    @Override
    public State getState(NodeId nodeId) {
        checkNotNull(nodeId, INSTANCE_ID_NULL);
        return firstNonNull(nodeStates.get(nodeId), State.INACTIVE);
    }

    @Override
    public Version getVersion(NodeId nodeId) {
        checkNotNull(nodeId, INSTANCE_ID_NULL);
        return nodeVersions.get(nodeId);
    }

    @Override
    public void markFullyStarted(boolean started) {
        updateNode(localNode.id(), started ? State.READY : State.ACTIVE, null);
    }

    @Override
    public ControllerNode addNode(NodeId nodeId, IpAddress ip, int tcpPort) {
        checkNotNull(nodeId, INSTANCE_ID_NULL);
        ControllerNode node = new DefaultControllerNode(nodeId, ip, tcpPort);
        addNode(node);
        return node;
    }

    @Override
    public void removeNode(NodeId nodeId) {
        checkNotNull(nodeId, INSTANCE_ID_NULL);
        ControllerNode node = allNodes.remove(nodeId);
        if (node != null) {
            nodeStates.remove(nodeId);
            nodeVersions.remove(nodeId);
            notifyDelegate(new ClusterEvent(ClusterEvent.Type.INSTANCE_REMOVED, node));
        }
    }

    private void addNode(ControllerNode node) {
        allNodes.put(node.id(), node);
        updateNode(node.id(), node.equals(localNode) ? State.ACTIVE : State.INACTIVE, null);
        notifyDelegate(new ClusterEvent(ClusterEvent.Type.INSTANCE_ADDED, node));
    }

    private void updateNode(NodeId nodeId, State newState, Version newVersion) {
        State currentState = nodeStates.get(nodeId);
        Version currentVersion = nodeVersions.get(nodeId);
        if (!Objects.equals(currentState, newState)
                || (newVersion != null && !Objects.equals(currentVersion, newVersion))) {
            nodeStates.put(nodeId, newState);
            if (newVersion != null) {
                nodeVersions.put(nodeId, newVersion);
            }
            nodeLastUpdatedTimes.put(nodeId, Instant.now());
            notifyChange(nodeId, currentState, newState, currentVersion, newVersion);
        }
    }

    private void heartbeat() {
        try {
            Set<ControllerNode> peers = allNodes.values()
                    .stream()
                    .filter(node -> !(node.id().equals(localNode.id())))
                    .collect(Collectors.toSet());
            State state = nodeStates.get(localNode.id());
            byte[] hbMessagePayload = SERIALIZER.encode(new HeartbeatMessage(localNode, state, localVersion));
            peers.forEach((node) -> {
                heartbeatToPeer(hbMessagePayload, node);
                State currentState = nodeStates.get(node.id());
                double phi = failureDetector.phi(node.id());
                if (phi >= phiFailureThreshold) {
                    if (currentState.isActive()) {
                        updateNode(node.id(), State.INACTIVE, null);
                        failureDetector.reset(node.id());
                    }
                } else {
                    if (currentState == State.INACTIVE) {
                        updateNode(node.id(), State.ACTIVE, null);
                    }
                }
            });
        } catch (Exception e) {
            log.debug("Failed to send heartbeat", e);
        }
    }

    private void notifyChange(NodeId nodeId, State oldState, State newState, Version oldVersion, Version newVersion) {
        if (oldState != newState || !Objects.equals(oldVersion, newVersion)) {
            ControllerNode node = allNodes.get(nodeId);
            // Either this node or that node is no longer part of the same cluster
            if (node == null) {
                log.debug("Could not find node {} in the cluster, ignoring state change", nodeId);
                return;
            }
            ClusterEvent.Type type = newState == State.READY ? INSTANCE_READY :
                    newState == State.ACTIVE ? INSTANCE_ACTIVATED :
                            INSTANCE_DEACTIVATED;
            notifyDelegate(new ClusterEvent(type, node));
        }
    }

    private void heartbeatToPeer(byte[] messagePayload, ControllerNode peer) {
        Endpoint remoteEp = new Endpoint(peer.ip(), peer.tcpPort());
        messagingService.sendAsync(remoteEp, HEARTBEAT_MESSAGE, messagePayload).whenComplete((result, error) -> {
            if (error != null) {
                log.trace("Sending heartbeat to {} failed", remoteEp, error);
            }
        });
    }

    private class HeartbeatMessageHandler implements BiConsumer<Endpoint, byte[]> {
        @Override
        public void accept(Endpoint sender, byte[] message) {
            HeartbeatMessage hb = SERIALIZER.decode(message);
            if (clusterMetadataService.getClusterMetadata().getNodes().contains(hb.source())) {
                // Avoid reporting heartbeats that have been enqueued by setting a minimum interval.
                long heartbeatTime = System.currentTimeMillis();
                long lastHeartbeatTime = failureDetector.getLastHeartbeatTime(hb.source().id());
                if (heartbeatTime - lastHeartbeatTime > heartbeatInterval / 2) {
                    failureDetector.report(hb.source().id(), heartbeatTime);
                }
                updateNode(hb.source().id(), hb.state, hb.version);
            }
        }
    }

    private static class HeartbeatMessage {
        private ControllerNode source;
        private State state;
        private Version version;

        public HeartbeatMessage(ControllerNode source, State state, Version version) {
            this.source = source;
            this.state = state != null ? state : State.ACTIVE;
            this.version = version;
        }

        public ControllerNode source() {
            return source;
        }
    }

    @Override
    public Instant getLastUpdatedInstant(NodeId nodeId) {
        return nodeLastUpdatedTimes.get(nodeId);
    }

    /**
     * Extracts properties from the component configuration.
     *
     */
    private void readComponentConfiguration() {
        Set<ConfigProperty> configProperties = cfgService.getProperties(getClass().getName());
        for (ConfigProperty property : configProperties) {
            if ("heartbeatInterval".equals(property.name())) {
                String s = property.value();
                if (s == null) {
                    setHeartbeatInterval(DEFAULT_HEARTBEAT_INTERVAL);
                    log.info("Heartbeat interval time is not configured, default value is {}",
                            DEFAULT_HEARTBEAT_INTERVAL);
                } else {
                    int newHeartbeatInterval = isNullOrEmpty(s) ? DEFAULT_HEARTBEAT_INTERVAL
                            : Integer.parseInt(s.trim());
                    if (newHeartbeatInterval > 0 && heartbeatInterval != newHeartbeatInterval) {
                        heartbeatInterval = newHeartbeatInterval;
                        restartHeartbeatSender();
                    }
                    log.info("Configured. Heartbeat interval time is configured to {}",
                            heartbeatInterval);
                }
            }
            if ("phiFailureThreshold".equals(property.name())) {
                String s = property.value();
                if (s == null) {
                    setPhiFailureThreshold(DEFAULT_PHI_FAILURE_THRESHOLD);
                    log.info("Phi failure threshold is not configured, default value is {}",
                            DEFAULT_PHI_FAILURE_THRESHOLD);
                } else {
                    int newPhiFailureThreshold = isNullOrEmpty(s) ? DEFAULT_HEARTBEAT_INTERVAL
                            : Integer.parseInt(s.trim());
                    setPhiFailureThreshold(newPhiFailureThreshold);
                    log.info("Configured. Phi failure threshold is configured to {}",
                            phiFailureThreshold);
                }
            }
        }
    }

    /**
     * Sets heartbeat interval between the termination of one execution of heartbeat
     * and the commencement of the next.
     *
     * @param interval term between each heartbeat
     */
    private void setHeartbeatInterval(int interval) {
        try {
            checkArgument(interval > 0, "Interval must be greater than zero");
            heartbeatInterval = interval;
        } catch (IllegalArgumentException e) {
            log.warn(e.getMessage());
            heartbeatInterval = DEFAULT_HEARTBEAT_INTERVAL;
        }
    }

    /**
     * Sets Phi failure threshold.
     * Phi is based on a paper titled: "The φ Accrual Failure Detector" by Hayashibara, et al.
     *
     * @param threshold
     */
    private void setPhiFailureThreshold(int threshold) {
        phiFailureThreshold = threshold;
    }

    /**
     * Restarts heartbeatSender executor.
     */
    private void restartHeartbeatSender() {
        try {
            ScheduledExecutorService prevSender = heartBeatSender;
            heartBeatSender = Executors.newSingleThreadScheduledExecutor(
                    groupedThreads("onos/cluster/membership", "heartbeat-sender-%d", log));
            heartBeatSender.scheduleWithFixedDelay(this::heartbeat, 0,
                    heartbeatInterval, TimeUnit.MILLISECONDS);
            prevSender.shutdown();
        } catch (Exception e) {
            log.warn(e.getMessage());
        }
    }
}