/*
 * Copyright 2015 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.link.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

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.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.PortNumber;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkProvider;
import org.onosproject.net.link.LinkProviderRegistry;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;

import java.util.Dictionary;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.util.Tools.groupedThreads;
import static org.onlab.util.Tools.toHex;
import static org.onosproject.net.MastershipRole.MASTER;
import static org.onosproject.net.Link.Type.DIRECT;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Provider which advertises fake/nonexistent links to the core. To be used for
 * benchmarking only.
 *
 * This provider takes a topology graph file with a DOT-like syntax.
 */
@Component(immediate = true)
public class NullLinkProvider extends AbstractProvider implements LinkProvider {

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

    // default topology file location and name.
    private static final String CFG_PATH = "/opt/onos/apache-karaf-3.0.2/etc/linkGraph.cfg";
    // default number of workers. Eventually make this tunable
    private static final int THREADS = 8;

    private static final int CHECK_DURATION = 10;
    private static final int DEFAULT_RATE = 0; // usec
    private static final int REFRESH_RATE = 3; // sec

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected MastershipService roleService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ClusterService nodeService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkProviderRegistry providerRegistry;

    private LinkProviderService providerService;

    private final InternalLinkProvider linkProvider = new InternalLinkProvider();

    // True for device with Driver, false otherwise.
    private final ConcurrentMap<DeviceId, Set<LinkDriver>> driverMap = Maps
            .newConcurrentMap();

    // Link descriptions
    private final Set<LinkDescription> linkDescrs = Sets.newConcurrentHashSet();

    // Thread to description map
    private final List<Set<LinkDescription>> linkTasks = new ArrayList<>(THREADS);

    private ScheduledExecutorService linkDriver =
            Executors.newScheduledThreadPool(THREADS, groupedThreads("onos/null", "link-driver-%d"));

    // For flicker = true, duration between events in msec.
    @Property(name = "eventRate", value = "0", label = "Duration between Link Event")
    private int eventRate = DEFAULT_RATE;

    // topology configuration file
    @Property(name = "cfgFile",
            value = "/opt/onos/apache-karaf-3.0.2/etc/linkGraph.cfg",
            label = "Topology file location")
    private String cfgFile = CFG_PATH;

    // flag checked to create a LinkDriver, if rate is non-zero.
    private boolean flicker = false;

    public NullLinkProvider() {
        super(new ProviderId("null", "org.onosproject.provider.nil"));
    }

    @Activate
    public void activate(ComponentContext context) {
        providerService = providerRegistry.register(this);
        modified(context);

        if (flicker) {
            allocateLinks();
            for (int i = 0; i < linkTasks.size(); i++) {
                Set<LinkDescription> links = linkTasks.get(i);
                LinkDriver driver = new LinkDriver(links, i);
                links.forEach(v -> {
                    DeviceId d = v.src().deviceId();
                    Set<LinkDriver> s = driverMap.getOrDefault(d, Sets.newConcurrentHashSet());
                    s.add(driver);
                    driverMap.put(d, s);
                });
                try {
                    linkDriver.schedule(driver, eventRate, TimeUnit.MICROSECONDS);
                } catch (Exception e) {
                    log.warn(e.getMessage());
                }
            }
        } else {
            linkDriver.schedule(new LinkDriver(linkDescrs, 0), 3, TimeUnit.SECONDS);
        }
        log.info("started");
    }

    @Deactivate
    public void deactivate(ComponentContext context) {
        linkDriver.shutdown();
        try {
            linkDriver.awaitTermination(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            log.error("LinkBuilder did not terminate");
            linkDriver.shutdownNow();
        }
        deviceService.removeListener(linkProvider);
        providerRegistry.unregister(this);
        deviceService = null;

        log.info("stopped");
    }

    @Modified
    public void modified(ComponentContext context) {
        if (context == null) {
            log.info("No configs, using defaults: eventRate={}", DEFAULT_RATE);
            return;
        }
        Dictionary<?, ?> properties = context.getProperties();
        int newRate;
        String newPath;
        try {
            String s = (String) properties.get("eventRate");
            newRate = isNullOrEmpty(s) ? eventRate : Integer.parseInt(s.trim());
            s = (String) properties.get("cfgFile");
            newPath = s.trim();
        } catch (NumberFormatException | ClassCastException e) {
            log.warn(e.getMessage());
            newRate = eventRate;
            newPath = cfgFile;
        }

        // topology file configuration
        if (!newPath.equals(cfgFile)) {
            cfgFile = newPath;
        }
        readGraph(cfgFile, nodeService.getLocalNode().id());

        // test mode configuration
        if (eventRate != newRate && newRate > 0) {
            eventRate = newRate;
            flicker = true;
        } else if (newRate == 0) {
            flicker = false;
        }

        log.info("Using settings: eventRate={}, topofile={}", eventRate, cfgFile);
    }

    // parse simplified dot-like topology graph
    private void readGraph(String path, NodeId me) {
        log.info("path: {}, local: {}", path, me);
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(path));
            String cur = br.readLine();
            while (cur != null) {
                if (cur.startsWith("#")) {
                    cur = br.readLine();
                    continue;
                }
                String[] parts = cur.trim().split(" ");
                if (parts.length < 1) {
                    continue;
                }
                if (parts[0].equals("graph")) {
                    String node = parts[1].trim();
                    if (node.equals(me.toString())) {
                        cur = br.readLine(); // move to next line, start of links list
                        while (cur != null) {
                            if (cur.trim().contains("}")) {
                                break;
                            }
                            readLink(cur.trim().split(" "), me);
                            cur = br.readLine();
                        }
                    } else {
                        while (cur != null) {
                            if (cur.trim().equals("}")) {
                                break;
                            }
                            cur = br.readLine();
                        }
                    }
                }
                cur = br.readLine();
            }
        } catch (IOException e) {
            log.warn("Could not find topology file: {}", e);
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                log.warn("Could not close topology file: {}", e);
            }
        }
    }

    // parses a link descriptor to make a LinkDescription
    private void readLink(String[] linkArr, NodeId me) {
        if (linkArr[0].startsWith("#")) {
            return;
        }
        if (linkArr.length != 3) {
            log.warn("Malformed link descriptor:"
                    + " link should be of format src:port [--|->] dst:port,"
                    + " skipping");
            return;
        }

        String op = linkArr[1];
        String[] cp1 = linkArr[0].split(":");
        String[] cp2 = linkArr[2].split(":");

        if (cp1.length != 2 && (cp2.length != 2 || cp2.length != 3)) {
            log.warn("Malformed endpoint descriptor(s):"
                    + "endpoint format should be DeviceId:port or DeviceId:port:NodeId,"
                    + "skipping");
            return;
        }
        // read in hints about topology.
        NodeId adj = null;
        if (cp2.length == 3) {
            adj = new NodeId(cp2[2]);
            log.debug("found an island: {}", adj);
        }

        // reconstruct deviceIDs. Convention is based on NullDeviceProvider.
        DeviceId sdev = recover(cp1[0], me);
        DeviceId ddev = (adj == null) ? recover(cp2[0], me) : recover(cp2[0], adj);
        ConnectPoint src = new ConnectPoint(sdev, PortNumber.portNumber(cp1[1]));
        ConnectPoint dst = new ConnectPoint(ddev, PortNumber.portNumber(cp2[1]));
        // both link types have incoming half-link
        LinkDescription in = new DefaultLinkDescription(dst, src, DIRECT);
        linkDescrs.add(in);
        if (op.equals("--")) {
            // bidirectional - within our node's island, make outbound link
            LinkDescription out = new DefaultLinkDescription(src, dst, DIRECT);
            linkDescrs.add(out);
            log.info("Created bidirectional link: {}, {}", out, in);
        } else if (op.equals("->")) {
            log.info("Created unidirectional link: {}", in);
        } else {
            log.warn("Unknown link descriptor operand:"
                    + " operand must be '--' or '->', skipping");
            return;
        }
    }

    // recover DeviceId from configs and NodeID
    private DeviceId recover(String base, NodeId node) {
        long hash = node.hashCode() << 16;
        int dev = Integer.valueOf(base);
        try {
            return DeviceId.deviceId(new URI("null", toHex(hash | dev), null));
        } catch (URISyntaxException e) {
            log.warn("could not create a DeviceID for descriptor {}", dev);
            return DeviceId.NONE;
        }
    }

    // adds a LinkDescription to a worker's to-be queue, for flickering
    private void allocateLinks() {
        int index, lcount = 0;
        for (LinkDescription ld : linkDescrs) {
            index = (lcount % THREADS);
            log.info("allocation: total={}, index={}", linkDescrs.size(), lcount, index);
            if (linkTasks.size() <= index) {
                linkTasks.add(index, Sets.newHashSet(ld));
            } else {
                linkTasks.get(index).add(ld);
            }
            lcount++;
        }
    }

    /**
     * Generate LinkEvents using configurations when devices are found.
     */
    private class InternalLinkProvider implements DeviceListener {

        @Override
        public void event(DeviceEvent event) {
            Device dev = event.subject();
            switch (event.type()) {
            case DEVICE_ADDED:
                // TODO: wait for all devices to stop core from balking
                break;
            case DEVICE_REMOVED:
                if (MASTER.equals(roleService.getLocalRole(dev.id()))) {
                    for (LinkDriver d : driverMap.get(dev.id())) {
                        d.deviceRemoved(dev.id());
                    }
                }
                providerService.linksVanished(dev.id());
                break;
            default:
                break;
            }
        }
    }

    /**
     * Generates link events using fake links.
     * TODO: stats collection should be its own thing.
     */
    private class LinkDriver implements Runnable {
        // List to actually work off of
        List<LinkDescription> tasks = Lists.newArrayList();
        float effLoad = 0;
        Long counter = 0L;
        int next = 0;

        long startTime;

        LinkDriver(Set<LinkDescription> links, int index) {
            for (LinkDescription link : links) {
                tasks.add(link);
            }
            startTime = System.currentTimeMillis();
        }

        @Override
        public void run() {
            log.info("Thread started for links {}", tasks);
            if (flicker) {
                flicker();
            } else {
                refresh();
            }
        }

        private void flicker() {
            if ((!linkDriver.isShutdown() || !tasks.isEmpty())) {
                log.info("next: {}, count: {}", next, counter);
                if (counter <= CHECK_DURATION * 1000000 / eventRate) {
                    if ((counter % 2) == 0) {
                        providerService.linkVanished(tasks.get(next++));
                    } else {
                        providerService.linkDetected(tasks.get(next++));
                    }
                    if (next == tasks.size()) {
                        next = 0;
                    }
                    counter++;
                } else {
                    // log in WARN the effective load generation rate in events/sec, every 10 seconds
                    effLoad = (float) (counter * 1000.0 / (System
                            .currentTimeMillis() - startTime));
                    log.warn("Effective Loading for thread is {} events/second",
                            String.valueOf(effLoad));
                    counter = 0L;
                    startTime = System.currentTimeMillis();
                }
                linkDriver.schedule(this, eventRate, TimeUnit.MICROSECONDS);
            }
        }

        private void refresh() {
            if (!linkDriver.isShutdown() || !tasks.isEmpty()) {
                log.info("iter {} refresh_links for {} links", counter, linkDescrs.size());

                for (LinkDescription desc : linkDescrs) {
                    providerService.linkDetected(desc);
                    log.info("iteration {}, {}", counter, desc);
                }
                counter++;
                linkDriver.schedule(this, REFRESH_RATE, TimeUnit.SECONDS);
            }
        }

        public void deviceRemoved(DeviceId did) {
            synchronized (tasks) {
                Iterator<LinkDescription> it = tasks.iterator();
                while (it.hasNext()) {
                    LinkDescription ld = it.next();
                    if (did.equals(ld.dst().deviceId())
                            || (did.equals(ld.src().deviceId()))) {
                        it.remove();
                    }
                }
            }
        }
    }

}
