/*
 * 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 static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.util.Tools.delay;
import static org.onlab.util.Tools.namedThreads;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.net.MastershipRole.MASTER;

import java.util.Dictionary;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

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.mastership.MastershipService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
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.LinkEvent;
import org.onosproject.net.link.LinkListener;
import org.onosproject.net.link.LinkProvider;
import org.onosproject.net.link.LinkProviderRegistry;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;

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

/**
 * Provider which advertises fake/nonexistent links to the core. To be used for
 * benchmarking only.
 */
@Component(immediate = true)
public class NullLinkProvider extends AbstractProvider implements LinkProvider {

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

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

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

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

    private LinkProviderService providerService;

    private static final boolean FLICKER = false;
    private static final int DEFAULT_RATE = 3000;
    // For now, static switch port values
    private static final PortNumber SRCPORT = PortNumber.portNumber(5);
    private static final PortNumber DSTPORT = PortNumber.portNumber(6);

    private final InternalLinkProvider linkProvider = new InternalLinkProvider();
    private final InternalLinkListener listener = new InternalLinkListener();

    // Link descriptions
    private final ConcurrentMap<ConnectPoint, LinkDescription> descriptions = Maps
            .newConcurrentMap();

    // Local Device ID's that have been seen so far
    private final List<DeviceId> devices = Lists.newArrayList();
    // tail ends of other islands
    private final List<ConnectPoint> tails = Lists.newArrayList();

    private ExecutorService linkDriver = Executors.newFixedThreadPool(1,
            namedThreads("onos-null-link-driver"));

    // If true, 'flickers' links by alternating link up/down events at eventRate
    @Property(name = "flicker", value = "false",
            label = "Setting to flap links")
    private boolean flicker = FLICKER;

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

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

    @Activate
    public void activate(ComponentContext context) {
        providerService = providerRegistry.register(this);
        linkService = (LinkService) providerRegistry;
        linkService.addListener(listener);
        deviceService.addListener(linkProvider);
        modified(context);
        log.info("started");
    }

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

        log.info("stopped");
    }

    @Modified
    public void modified(ComponentContext context) {
        if (context == null) {
            log.info("No configs, using defaults: flicker={}, eventRate={}",
                    FLICKER, DEFAULT_RATE);
            return;
        }
        Dictionary<?, ?> properties = context.getProperties();

        boolean flickSetting;
        int newRate;
        try {
            String s = (String) properties.get("flicker");
            flickSetting = isNullOrEmpty(s) ? flicker : Boolean.valueOf(s.trim());
            s = (String) properties.get("eventRate");
            newRate = isNullOrEmpty(s) ? eventRate : Integer.valueOf(s.trim());
        } catch (Exception e) {
            log.warn(e.getMessage());
            flickSetting = flicker;
            newRate = eventRate;
        }

        if (flicker != flickSetting) {
            flicker = flickSetting;
        }

        if (flicker) {
            if (eventRate != newRate) {
                eventRate = newRate;
            }
            linkDriver.submit(new LinkDriver());
        }
        log.info("Using new settings: flicker={}, eventRate={}", flicker,
                eventRate);
    }

    // pick out substring from Deviceid
    private String part(String devId) {
        return devId.split(":")[1].substring(12, 16);
    }

    /**
     * Adds links as devices are found, and generates LinkEvents.
     */
    private class InternalLinkProvider implements DeviceListener {

        @Override
        public void event(DeviceEvent event) {
            Device dev = event.subject();
            switch (event.type()) {
            case DEVICE_ADDED:
                addLink(dev);
                break;
            case DEVICE_REMOVED:
                removeLink(dev);
                break;
            default:
                break;
            }
        }

        private void addLink(Device current) {
            DeviceId did = current.id();
            if (!MASTER.equals(roleService.getLocalRole(did))) {
                String part = part(did.toString());
                if (part.equals("ffff")) {
                    // 'tail' of an island - link us <- tail
                    tails.add(new ConnectPoint(did, SRCPORT));
                }
                tryLinkTail();
                return;
            }
            devices.add(did);

            if (devices.size() == 1) {
                return;
            }

            // Normal flow - attach new device to the last-seen device
            DeviceId prev = devices.get(devices.size() - 2);
            ConnectPoint src = new ConnectPoint(prev, SRCPORT);
            ConnectPoint dst = new ConnectPoint(did, DSTPORT);

            LinkDescription fdesc = new DefaultLinkDescription(src, dst,
                    Link.Type.DIRECT);
            LinkDescription rdesc = new DefaultLinkDescription(dst, src,
                    Link.Type.DIRECT);
            descriptions.put(src, fdesc);
            descriptions.put(dst, rdesc);

            providerService.linkDetected(fdesc);
            providerService.linkDetected(rdesc);
        }

        // try to link to a tail to first element
        private void tryLinkTail() {
            if (tails.isEmpty() || devices.isEmpty()) {
                return;
            }
            ConnectPoint first = new ConnectPoint(devices.get(0), DSTPORT);
            boolean added = false;
            for (ConnectPoint cp : tails) {
                if (!linkService.getLinks(cp).isEmpty()) {
                    continue;
                }
                LinkDescription ld = new DefaultLinkDescription(cp, first,
                        Link.Type.DIRECT);
                descriptions.put(cp, ld);
                providerService.linkDetected(ld);
                added = true;
                break;
            }
            if (added) {
                tails.clear();
            }
        }

        private void removeLink(Device device) {
            if (!MASTER.equals(roleService.getLocalRole(device.id()))) {
                return;
            }
            providerService.linksVanished(device.id());
            devices.remove(device.id());
        }

    }

    private class InternalLinkListener implements LinkListener {

        @Override
        public void event(LinkEvent event) {
            switch (event.type()) {
            case LINK_ADDED:
                // If a link from another island, cast one back.
                DeviceId sdid = event.subject().src().deviceId();
                PortNumber pn = event.subject().src().port();

                if (roleService.getLocalRole(sdid).equals(MASTER)) {
                    String part = part(sdid.toString());
                    if (part.equals("ffff") && SRCPORT.equals(pn)) {
                        LinkDescription ld = new DefaultLinkDescription(event
                                .subject().dst(), event.subject().src(),
                                Link.Type.DIRECT);
                        descriptions.put(event.subject().dst(), ld);
                        providerService.linkDetected(ld);
                    }
                    return;
                }
                break;
            default:
                break;
            }
        }

    }

    /**
     * Generates link events using fake links.
     */
    private class LinkDriver implements Runnable {

        @Override
        public void run() {
            while (!linkDriver.isShutdown()) {
                for (LinkDescription desc : descriptions.values()) {
                    providerService.linkVanished(desc);
                    delay(eventRate);
                    providerService.linkDetected(desc);
                    delay(eventRate);
                }
            }
        }
    }
}
