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

import com.google.common.collect.Lists;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.NodeId;
import org.onosproject.mastership.MastershipAdminService;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.Link;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceAdminService;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.link.DefaultLinkDescription;
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.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static org.onlab.util.Tools.toHex;
import static org.onosproject.net.HostId.hostId;
import static org.onosproject.net.Link.Type.DIRECT;
import static org.onosproject.net.MastershipRole.MASTER;
import static org.onosproject.net.PortNumber.portNumber;
import static org.onosproject.net.device.DeviceEvent.Type.*;
import static org.onosproject.provider.nil.NullProviders.SCHEME;

/**
 * Abstraction of a provider capable to simulate some network topology.
 */
public abstract class TopologySimulator {

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

    protected String[] topoShape;
    protected int deviceCount;
    protected int hostCount;

    protected ServiceDirectory directory;
    protected NodeId localNode;

    protected ClusterService clusterService;
    protected MastershipService mastershipService;
    protected MastershipAdminService mastershipAdminService;

    protected DeviceAdminService deviceService;
    protected HostService hostService;
    protected LinkService linkService;

    protected DeviceProviderService deviceProviderService;
    protected HostProviderService hostProviderService;
    protected LinkProviderService linkProviderService;

    protected int maxWaitSeconds = 1;
    protected int infrastructurePorts = 2;
    protected CountDownLatch deviceLatch;

    protected final List<DeviceId> deviceIds = Lists.newArrayList();

    private final DeviceListener deviceEventCounter = new DeviceEventCounter();

    /**
     * Initializes a new topology simulator with access to the specified service
     * directory and various provider services.
     *
     * @param topoShape             topology shape specifier
     * @param deviceCount           number of devices in the topology
     * @param hostCount             number of hosts per device
     * @param directory             service directory
     * @param deviceProviderService device provider service
     * @param hostProviderService   host provider service
     * @param linkProviderService   link provider service
     */
    protected void init(String topoShape, int deviceCount, int hostCount,
                        ServiceDirectory directory,
                        DeviceProviderService deviceProviderService,
                        HostProviderService hostProviderService,
                        LinkProviderService linkProviderService) {
        this.deviceCount = deviceCount;
        this.hostCount = hostCount;
        this.directory = directory;

        this.clusterService = directory.get(ClusterService.class);
        this.mastershipService = directory.get(MastershipService.class);
        this.mastershipAdminService = directory.get(MastershipAdminService.class);

        this.deviceService = directory.get(DeviceAdminService.class);
        this.hostService = directory.get(HostService.class);
        this.linkService = directory.get(LinkService.class);
        this.deviceProviderService = deviceProviderService;
        this.hostProviderService = hostProviderService;
        this.linkProviderService = linkProviderService;

        localNode = clusterService.getLocalNode().id();

        processTopoShape(topoShape);
    }

    /**
     * Processes the topology shape specifier.
     *
     * @param shape topology shape specifier
     */
    protected void processTopoShape(String shape) {
        this.topoShape = shape.split(",");
    }

    /**
     * Sets up network topology simulation.
     */
    public void setUpTopology() {
        deviceIds.clear();
        prepareForDeviceEvents(deviceCount);
        createDevices();
        waitForDeviceEvents();

        createLinks();
        createHosts();
    }

    /**
     * Creates simulated devices.
     */
    protected void createDevices() {
        for (int i = 0; i < deviceCount; i++) {
            createDevice(i + 1);
        }
    }

    /**
     * Creates simulated links.
     */
    protected abstract void createLinks();

    /**
     * Creates simulated hosts.
     */
    protected abstract void createHosts();

    /**
     * Creates simulated device and adds its id to the list of devices ids.
     *
     * @param i index of the device id in the list.
     */
    protected void createDevice(int i) {
        createDevice(DeviceId.deviceId(SCHEME + ":" + toHex(i)), i);
    }

    /**
     * Creates simulated device.
     *
     * @param id        device identifier
     * @param chassisId chassis identifier number
     */
    public void createDevice(DeviceId id, int chassisId) {
        createDevice(id, chassisId, Device.Type.SWITCH, hostCount + infrastructurePorts);
    }

    /**
     * Creates simulated device.
     *
     * @param id        device identifier
     * @param chassisId chassis identifier number
     * @param type      device type
     * @param portCount number of device ports
     */
    public void createDevice(DeviceId id, int chassisId, Device.Type type, int portCount) {
        createDevice(id, chassisId, type, "0.1", "0.1.2", portCount);
    }

    /**
     * Creates simulated device.
     *
     * @param id        device identifier
     * @param chassisId chassis identifier number
     * @param type      device type
     * @param hw        hardware revision
     * @param sw        software revision
     * @param portCount number of device ports
     */
    public void createDevice(DeviceId id, int chassisId, Device.Type type,
                             String hw, String sw, int portCount) {
        DeviceDescription desc =
                new DefaultDeviceDescription(id.uri(), type, "ONF", hw, sw, "1234",
                                             new ChassisId(chassisId));
        deviceIds.add(id);
        mastershipAdminService.setRoleSync(localNode, id, MASTER);
        deviceProviderService.deviceConnected(id, desc);
        deviceProviderService.updatePorts(id, buildPorts(portCount));
    }

    /**
     * Creates simulated link between two devices.
     *
     * @param i  index of one simulated device
     * @param j  index of another simulated device
     * @param pi port number of i-th device
     * @param pj port number of j-th device
     */
    public void createLink(int i, int j, int pi, int pj) {
        ConnectPoint one = new ConnectPoint(deviceIds.get(i), PortNumber.portNumber(pi));
        ConnectPoint two = new ConnectPoint(deviceIds.get(j), PortNumber.portNumber(pj));
        createLink(one, two);
    }

    /**
     * Creates simulated link between two connection points.
     *
     * @param one one connection point
     * @param two another connection point
     */
    public void createLink(ConnectPoint one, ConnectPoint two) {
        createLink(one, two, DIRECT, true);
    }

    /**
     * Creates simulated link between two connection points.
     *
     * @param one             one connection point
     * @param two             another connection point
     * @param type            link type
     * @param isBidirectional true if link is bidirectional
     */
    public void createLink(ConnectPoint one, ConnectPoint two, Link.Type type, boolean isBidirectional) {
        linkProviderService.linkDetected(new DefaultLinkDescription(one, two, type));
        if (isBidirectional) {
            linkProviderService.linkDetected(new DefaultLinkDescription(two, one, type));
        }
    }

    /**
     * Creates simularted hosts for the specified device.
     *
     * @param deviceId   device identifier
     * @param portOffset port offset where to start attaching hosts
     */
    public void createHosts(DeviceId deviceId, int portOffset) {
        String s = deviceId.toString();
        byte dByte = Byte.parseByte(s.substring(s.length() - 2), 16);
        // TODO: this limits the simulation to 256 devices & 256 hosts/device.
        byte[] macBytes = new byte[]{0, 0, 0, 0, dByte, 0};
        byte[] ipBytes = new byte[]{(byte) 192, (byte) 168, dByte, 0};

        for (int i = 0; i < hostCount; i++) {
            int port = portOffset + i + 1;
            macBytes[5] = (byte) (i + 1);
            ipBytes[3] = (byte) (i + 1);
            HostId id = hostId(MacAddress.valueOf(macBytes), VlanId.NONE);
            IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET, ipBytes);
            hostProviderService.hostDetected(id, description(id, ip, deviceId, port), false);
        }
    }

    /**
     * Prepares to count device added/available/removed events.
     *
     * @param count number of events to count
     */
    protected void prepareForDeviceEvents(int count) {
        deviceLatch = new CountDownLatch(count);
        deviceService.addListener(deviceEventCounter);
    }

    /**
     * Waits for all expected device added/available/removed events.
     */
    protected void waitForDeviceEvents() {
        try {
            deviceLatch.await(maxWaitSeconds, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.warn("Device events did not arrive in time");
            Thread.currentThread().interrupt();
        }
        deviceService.removeListener(deviceEventCounter);
    }


    /**
     * Tears down network topology simulation.
     */
    public void tearDownTopology() {
        removeHosts();
        removeLinks();
        removeDevices();
    }

    /**
     * Removes any hosts previously advertised by this provider.
     */
    protected void removeHosts() {
        hostService.getHosts()
                .forEach(host -> hostProviderService.hostVanished(host.id()));
    }

    /**
     * Removes any links previously advertised by this provider.
     */
    protected void removeLinks() {
        linkService.getLinks()
                .forEach(link -> linkProviderService.linkVanished(description(link)));
    }

    /**
     * Removes any devices previously advertised by this provider.
     */
    protected void removeDevices() {
        prepareForDeviceEvents(deviceIds.size());
        deviceIds.forEach(deviceProviderService::deviceDisconnected);
        waitForDeviceEvents();
        mastershipService.getDevicesOf(localNode).forEach(mastershipService::relinquishMastership);
        deviceIds.forEach(mastershipService::relinquishMastership);
        deviceIds.clear();
    }


    /**
     * Produces a device description from the given device.
     *
     * @param device device to copy
     * @return device description
     */
    static DeviceDescription description(Device device) {
        return new DefaultDeviceDescription(device.id().uri(), device.type(),
                                            device.manufacturer(),
                                            device.hwVersion(), device.swVersion(),
                                            device.serialNumber(), device.chassisId());
    }

    /**
     * Produces a link description from the given link.
     *
     * @param link link to copy
     * @return link description
     */
    static DefaultLinkDescription description(Link link) {
        return new DefaultLinkDescription(link.src(), link.dst(), link.type());
    }

    /**
     * Produces a host description from the given host.
     *
     * @param host host to copy
     * @return host description
     */
    static DefaultHostDescription description(Host host) {
        return new DefaultHostDescription(host.mac(), host.vlan(), host.location(),
                                          host.ipAddresses());
    }

    /**
     * Generates a host description from the given id and location information.
     *
     * @param hostId   host identifier
     * @param ip       host IP
     * @param deviceId edge device
     * @param port     edge port
     * @return host description
     */
    static HostDescription description(HostId hostId, IpAddress ip,
                                       DeviceId deviceId, int port) {
        HostLocation location = new HostLocation(deviceId, portNumber(port), 0L);
        return new DefaultHostDescription(hostId.mac(), hostId.vlanId(), location, ip);
    }

    /**
     * Generates a list of a configured number of ports.
     *
     * @param portCount number of ports
     * @return list of ports
     */
    protected List<PortDescription> buildPorts(int portCount) {
        List<PortDescription> ports = Lists.newArrayList();
        for (int i = 1; i <= portCount; i++) {
            ports.add(DefaultPortDescription.builder()
                    .withPortNumber(PortNumber.portNumber(i))
                    .isEnabled(true)
                    .type(Port.Type.COPPER)
                    .portSpeed(0)
                    .build());
        }
        return ports;
    }

    /**
     * Indicates whether or not the simulation deeps the device as available.
     *
     * @param deviceId device identifier
     * @return true if device is known
     */
    public boolean contains(DeviceId deviceId) {
        return deviceIds.contains(deviceId);
    }

    // Counts down number of device added/available/removed events.
    private class DeviceEventCounter implements DeviceListener {
        @Override
        public void event(DeviceEvent event) {
            DeviceEvent.Type type = event.type();
            if (type == DEVICE_ADDED || type == DEVICE_REMOVED ||
                    type == DEVICE_AVAILABILITY_CHANGED) {
                deviceLatch.countDown();
            }
        }
    }
}
