/*
 * 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 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.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.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 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 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.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() {
        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) {
        DeviceId id = DeviceId.deviceId(SCHEME + ":" + toHex(i));
        deviceIds.add(id);
        createDevice(id, i);
    }

    /**
     * Creates simulated device.
     *
     * @param id device identifier
     * @param chassisId chassis identifier number
     */
    protected void createDevice(DeviceId id, int chassisId) {
        DeviceDescription desc =
                new DefaultDeviceDescription(id.uri(), Device.Type.SWITCH,
                                             "ON.Lab", "0.1", "0.1", "1234",
                                             new ChassisId(chassisId));
        deviceProviderService.deviceConnected(id, desc);
        deviceProviderService.updatePorts(id, buildPorts(hostCount + infrastructurePorts));
    }

    /**
     * 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
     */
    protected 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
     */
    protected void createLink(ConnectPoint one, ConnectPoint two) {
        linkProviderService.linkDetected(new DefaultLinkDescription(one, two, DIRECT));
        linkProviderService.linkDetected(new DefaultLinkDescription(two, one, DIRECT));
    }

    /**
     * Creates simularted hosts for the specified device.
     *
     * @param deviceId   device identifier
     * @param portOffset port offset where to start attaching hosts
     */
    protected 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");
        }
        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();
        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 = 0; i < portCount; i++) {
            ports.add(new DefaultPortDescription(PortNumber.portNumber(i), true,
                                                 Port.Type.COPPER, 0));
        }
        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();
            }
        }
    }
}
