/*
 * 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.drivers.p4runtime;

import org.onosproject.cluster.ClusterService;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.device.DeviceAgentListener;
import org.onosproject.net.device.DeviceHandshaker;
import org.onosproject.net.pi.service.PiPipeconfWatchdogService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.p4runtime.api.P4RuntimeClient;
import org.onosproject.p4runtime.api.P4RuntimeClientKey;
import org.onosproject.p4runtime.api.P4RuntimeController;

import java.math.BigInteger;
import java.util.concurrent.CompletableFuture;

import static java.util.concurrent.CompletableFuture.completedFuture;

/**
 * Implementation of DeviceHandshaker for P4Runtime.
 */
public class P4RuntimeHandshaker extends AbstractP4RuntimeHandlerBehaviour implements DeviceHandshaker {

    // This is needed to compute an election ID based on mastership term and
    // preference. At the time of writing the practical maximum cluster size is
    // 9. Since election IDs are 128bit numbers, we should'nt be too worried of
    // being conservative when setting a static max size here. Making the
    // cluster size dynamic would likely cause conflicts when generating
    // election IDs (e.g. two nodes seeing different cluster sizes).
    private static final int MAX_CLUSTER_SIZE = 20;

    @Override
    public CompletableFuture<Boolean> connect() {
        return CompletableFuture
                .supplyAsync(this::createClient);
    }

    private boolean createClient() {
        final P4RuntimeClientKey clientKey = clientKey();
        if (clientKey == null) {
            return false;
        }
        if (!handler().get(P4RuntimeController.class).createClient(clientKey)) {
            log.debug("Unable to create client for {}", data().deviceId());
            return false;
        }
        return true;
    }

    @Override
    public boolean isConnected() {
        // This is based on the client key obtained from the current netcfg. If
        // a client already exists for this device, but the netcfg with the
        // server endpoints has changed, this will return false.
        return getClientByKey() != null;
    }

    @Override
    public void disconnect() {
        // This removes clients associated with this device ID, even if the
        // netcfg has changed and so the client key for this device.
        handler().get(P4RuntimeController.class).removeClient(data().deviceId());
    }

    @Override
    public boolean isReachable() {
        final P4RuntimeClient client = getClientByKey();
        return client != null && client.isServerReachable();
    }

    @Override
    public CompletableFuture<Boolean> probeReachability() {
        final P4RuntimeClient client = getClientByKey();
        if (client == null) {
            return completedFuture(false);
        }
        return client.probeService();
    }

    @Override
    public boolean isAvailable() {
        // To be available, we require a session open (for packet in/out) and a
        // pipeline config set.
        final P4RuntimeClient client = getClientByKey();
        if (client == null || !client.isServerReachable() || !client.isSessionOpen()) {
            return false;
        }
        // Since we cannot probe the device, we rely on what's known by the
        // pipeconf watchdog service.
        return PiPipeconfWatchdogService.PipelineStatus.READY.equals(
                handler().get(PiPipeconfWatchdogService.class)
                        .getStatus(data().deviceId()));
    }

    @Override
    public CompletableFuture<Boolean> probeAvailability() {
        // To be available, we require a session open (for packet in/out) and a
        // pipeline config set.
        final P4RuntimeClient client = getClientByKey();
        if (client == null || !client.isServerReachable() || !client.isSessionOpen()) {
            return completedFuture(false);
        }
        return client.isAnyPipelineConfigSet();
    }

    @Override
    public void roleChanged(MastershipRole newRole) {
        if (newRole.equals(MastershipRole.NONE)) {
            final P4RuntimeClient client = getClientByKey();
            if (client != null) {
                log.info("Notified role NONE, closing session...");
                client.closeSession();
            }
        } else {
            throw new UnsupportedOperationException(
                    "Use preference-based way for setting MASTER or STANDBY roles");
        }
    }

    @Override
    public void roleChanged(int preference, long term) {
        if (setupBehaviour()) {
            final int clusterSize = handler().get(ClusterService.class)
                    .getNodes().size();
            if (clusterSize > MAX_CLUSTER_SIZE) {
                throw new IllegalStateException(
                        "Cluster too big! Maz size supported is " + MAX_CLUSTER_SIZE);
            }
            BigInteger electionId = BigInteger.valueOf(term)
                    .multiply(BigInteger.valueOf(MAX_CLUSTER_SIZE))
                    .subtract(BigInteger.valueOf(preference));
            client.setMastership(preference == 0, electionId);
        }
    }

    @Override
    public MastershipRole getRole() {
        final P4RuntimeClient client = getClientByKey();
        if (client == null || !client.isServerReachable() || !client.isSessionOpen()) {
            return MastershipRole.NONE;
        }
        return client.isMaster() ? MastershipRole.MASTER : MastershipRole.STANDBY;
    }

    @Override
    public void addDeviceAgentListener(ProviderId providerId, DeviceAgentListener listener) {
        // Don't use controller/deviceId class variables as they might be uninitialized.
        handler().get(P4RuntimeController.class)
                .addDeviceAgentListener(data().deviceId(), providerId, listener);
    }

    @Override
    public void removeDeviceAgentListener(ProviderId providerId) {
        // Don't use controller/deviceId class variable as they might be uninitialized.
        handler().get(P4RuntimeController.class)
                .removeDeviceAgentListener(data().deviceId(), providerId);
    }
}
