/*
 * 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.net.newresource.impl;

import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Link;
import org.onosproject.net.LinkKey;
import org.onosproject.net.behaviour.MplsQuery;
import org.onosproject.net.behaviour.VlanQuery;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.link.LinkEvent;
import org.onosproject.net.link.LinkListener;
import org.onosproject.net.newresource.ResourceAdminService;
import org.onosproject.net.newresource.ResourcePath;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * An implementation of LinkListener registering links as resources.
 */
final class ResourceLinkListener implements LinkListener {

    private static final int TOTAL_VLANS = 1024;
    private static final List<VlanId> ENTIRE_VLAN_IDS = getEntireVlans();

    private static final int TOTAL_MPLS_LABELS = 1048576;
    private static final List<MplsLabel> ENTIRE_MPLS_LABELS = getEntireMplsLabels();

    private final ResourceAdminService adminService;
    private final DriverService driverService;
    private final ExecutorService executor;

    /**
     * Creates an instance with the specified ResourceAdminService and ExecutorService.
     *
     * @param adminService instance invoked to register resources
     * @param driverService driver service instance
     * @param executor executor used for processing resource registration
     */
    ResourceLinkListener(ResourceAdminService adminService, DriverService driverService, ExecutorService executor) {
        this.adminService = checkNotNull(adminService);
        this.driverService = checkNotNull(driverService);
        this.executor = checkNotNull(executor);
    }

    @Override
    public void event(LinkEvent event) {
        Link link = event.subject();
        switch (event.type()) {
            case LINK_ADDED:
                registerLinkResource(link);
                break;
            case LINK_REMOVED:
                unregisterLinkResource(link);
                break;
            default:
                break;
        }
    }

    private void registerLinkResource(Link link) {
        executor.submit(() -> {
            // register the link
            LinkKey linkKey = LinkKey.linkKey(link);
            adminService.registerResources(ResourcePath.ROOT, linkKey);

            ResourcePath linkPath = ResourcePath.discrete(linkKey);
            // register VLAN IDs against the link
            if (isEnabled(link, this::isVlanEnabled)) {
                adminService.registerResources(linkPath, ENTIRE_VLAN_IDS);
            }

            // register MPLS labels against the link
            if (isEnabled(link, this::isMplsEnabled)) {
                adminService.registerResources(linkPath, ENTIRE_MPLS_LABELS);
            }
        });
    }

    private void unregisterLinkResource(Link link) {
        LinkKey linkKey = LinkKey.linkKey(link);
        executor.submit(() -> adminService.unregisterResources(ResourcePath.ROOT, linkKey));
    }

    private boolean isEnabled(Link link, Predicate<ConnectPoint> predicate) {
        return predicate.test(link.src()) && predicate.test(link.dst());
    }

    private boolean isVlanEnabled(ConnectPoint cp) {
        try {
            DriverHandler handler = driverService.createHandler(cp.deviceId());
            if (handler == null) {
                return false;
            }

            VlanQuery query = handler.behaviour(VlanQuery.class);
            return query != null && query.isEnabled(cp.port());
        } catch (ItemNotFoundException e) {
            return false;
        }
    }

    private boolean isMplsEnabled(ConnectPoint cp) {
        try {
            DriverHandler handler = driverService.createHandler(cp.deviceId());
            if (handler == null) {
                return false;
            }

            MplsQuery query = handler.behaviour(MplsQuery.class);
            return query != null && query.isEnabled(cp.port());
        } catch (ItemNotFoundException e) {
            return false;
        }
    }

    private static List<VlanId> getEntireVlans() {
        return IntStream.range(0, TOTAL_VLANS)
                .mapToObj(x -> VlanId.vlanId((short) x))
                .collect(Collectors.toList());
    }

    private static List<MplsLabel> getEntireMplsLabels() {
        // potentially many objects are created
        return IntStream.range(0, TOTAL_MPLS_LABELS)
                .mapToObj(MplsLabel::mplsLabel)
                .collect(Collectors.toList());
    }
}
