/*
 * Copyright 2015-present 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.provider.nil;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.link.LinkService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.delay;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.Link.Type.DIRECT;
import static org.onosproject.net.MastershipRole.MASTER;
import static org.onosproject.provider.nil.TopologySimulator.description;

/**
 * Drives topology mutations at a specified rate of events per second.
 */
class TopologyMutationDriver implements Runnable {

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

    private static final int WAIT_DELAY = 2_000;
    private static final int MAX_DOWN_LINKS = 5;

    private final Random random = new Random();

    private volatile boolean stopped = true;

    private double mutationRate;
    private int millis, nanos;

    private LinkService linkService;
    private DeviceService deviceService;
    private LinkProviderService linkProviderService;
    private DeviceProviderService deviceProviderService;
    private TopologySimulator simulator;

    private List<LinkDescription> activeLinks;
    private List<LinkDescription> inactiveLinks;

    private final ExecutorService executor =
            newSingleThreadScheduledExecutor(groupedThreads("onos/null", "topo-mutator", log));

    private Map<DeviceId, Set<Link>> savedLinks = Maps.newConcurrentMap();

    /**
     * Starts the mutation process.
     *
     * @param mutationRate          link events per second
     * @param linkService           link service
     * @param deviceService         device service
     * @param linkProviderService   link provider service
     * @param deviceProviderService device provider service
     * @param simulator             topology simulator
     */
    void start(double mutationRate,
               LinkService linkService, DeviceService deviceService,
               LinkProviderService linkProviderService,
               DeviceProviderService deviceProviderService,
               TopologySimulator simulator) {
        savedLinks.clear();
        stopped = false;
        this.linkService = linkService;
        this.deviceService = deviceService;
        this.linkProviderService = linkProviderService;
        this.deviceProviderService = deviceProviderService;
        this.simulator = simulator;
        activeLinks = reduceLinks();
        inactiveLinks = Lists.newArrayList();
        adjustRate(mutationRate);
        executor.execute(this);
    }

    /**
     * Adjusts the topology mutation rate.
     *
     * @param mutationRate new topology mutation rate
     */
    void adjustRate(double mutationRate) {
        this.mutationRate = mutationRate;
        if (mutationRate > 0) {
            this.millis = (int) (1_000 / mutationRate / 2);
            this.nanos = (int) (1_000_000 / mutationRate / 2) % 1_000_000;
        } else {
            this.millis = 0;
            this.nanos = 0;
        }
        log.info("Settings: millis={}, nanos={}", millis, nanos);
    }

    /**
     * Stops the mutation process.
     */
    void stop() {
        stopped = true;
    }

    /**
     * Severs the link between the specified end-points in both directions.
     *
     * @param one link endpoint
     * @param two link endpoint
     */
    void severLink(ConnectPoint one, ConnectPoint two) {
        LinkDescription link = new DefaultLinkDescription(one, two, DIRECT);
        linkProviderService.linkVanished(link);
        linkProviderService.linkVanished(reverse(link));

    }

    /**
     * Repairs the link between the specified end-points in both directions.
     *
     * @param one link endpoint
     * @param two link endpoint
     */
    void repairLink(ConnectPoint one, ConnectPoint two) {
        LinkDescription link = new DefaultLinkDescription(one, two, DIRECT);
        linkProviderService.linkDetected(link);
        linkProviderService.linkDetected(reverse(link));
    }

    /**
     * Fails the specified device.
     *
     * @param deviceId device identifier
     */
    void failDevice(DeviceId deviceId) {
        savedLinks.put(deviceId, linkService.getDeviceLinks(deviceId));
        deviceProviderService.deviceDisconnected(deviceId);
    }

    /**
     * Repairs the specified device.
     *
     * @param deviceId device identifier
     */
    void repairDevice(DeviceId deviceId) {
        int chassisId = Integer.parseInt(deviceId.uri().getSchemeSpecificPart());
        simulator.createDevice(deviceId, chassisId);
        Set<Link> links = savedLinks.remove(deviceId);
        if (links != null) {
            links.forEach(l -> linkProviderService
                    .linkDetected(new DefaultLinkDescription(l.src(), l.dst(), DIRECT)));
        }
    }

    /**
     * Returns whether the given device is considered reachable or not.
     *
     * @param deviceId device identifier
     * @return true if device is reachable
     */
    boolean isReachable(DeviceId deviceId) {
        return !savedLinks.containsKey(deviceId);
    }

    @Override
    public void run() {
        delay(WAIT_DELAY);

        while (!stopped) {
            if (mutationRate > 0 && inactiveLinks.isEmpty()) {
                primeInactiveLinks();
            } else if (mutationRate <= 0 && !inactiveLinks.isEmpty()) {
                repairInactiveLinks();
            } else if (inactiveLinks.isEmpty()) {
                delay(WAIT_DELAY);

            } else {
                activeLinks.add(repairLink());
                pause();
                inactiveLinks.add(severLink());
                pause();
            }
        }
    }

    // Primes the inactive links with a few random links.
    private void primeInactiveLinks() {
        for (int i = 0, n = Math.min(MAX_DOWN_LINKS, activeLinks.size()); i < n; i++) {
            inactiveLinks.add(severLink());
        }
    }

    // Repairs all inactive links.
    private void repairInactiveLinks() {
        while (!inactiveLinks.isEmpty()) {
            repairLink();
        }
    }

    // Picks a random active link and severs it.
    private LinkDescription severLink() {
        LinkDescription link = getRandomLink(activeLinks);
        linkProviderService.linkVanished(link);
        linkProviderService.linkVanished(reverse(link));
        return link;
    }

    // Picks a random inactive link and repairs it.
    private LinkDescription repairLink() {
        LinkDescription link = getRandomLink(inactiveLinks);
        linkProviderService.linkDetected(link);
        linkProviderService.linkDetected(reverse(link));
        return link;
    }

    // Produces a reverse of the specified link.
    private LinkDescription reverse(LinkDescription link) {
        return new DefaultLinkDescription(link.dst(), link.src(), link.type());
    }

    // Returns a random link from the specified list of links.
    private LinkDescription getRandomLink(List<LinkDescription> links) {
        return links.remove(random.nextInt(links.size()));
    }

    // Reduces the given list of links to just a single link in each original pair.
    private List<LinkDescription> reduceLinks() {
        List<LinkDescription> links = Lists.newArrayList();
        linkService.getLinks().forEach(link -> links.add(description(link)));
        return links.stream()
                .filter(this::isOurLink)
                .filter(this::isRightDirection)
                .collect(Collectors.toList());
    }

    // Returns true if the specified link is ours.
    private boolean isOurLink(LinkDescription linkDescription) {
        return deviceService.getRole(linkDescription.src().deviceId()) == MASTER;
    }

    // Returns true if the link source is greater than the link destination.
    private boolean isRightDirection(LinkDescription link) {
        return link.src().deviceId().toString().compareTo(link.dst().deviceId().toString()) > 0;
    }

    // Pauses the current thread for the pre-computed time of millis & nanos.
    private void pause() {
        delay(millis, nanos);
    }

}
