/*
 * Copyright 2016-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.net.resource.impl;

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

import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onlab.util.Bandwidth;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.GridType;
import org.onosproject.net.OchSignal;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.TributarySlot;
import org.onosproject.net.behaviour.LambdaQuery;
import org.onosproject.net.behaviour.MplsQuery;
import org.onosproject.net.behaviour.TributarySlotQuery;
import org.onosproject.net.behaviour.VlanQuery;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.resource.DiscreteResource;
import org.onosproject.net.resource.ResourceAdminService;
import org.onosproject.net.config.basics.BandwidthCapacity;
import org.onosproject.net.resource.Resource;
import org.onosproject.net.resource.ResourceQueryService;
import org.onosproject.net.resource.Resources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import java.util.stream.Stream;

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

/**
 * An implementation of DeviceListener registering devices as resources.
 */
final class ResourceDeviceListener implements DeviceListener {

    private static final Logger log = LoggerFactory.getLogger(ResourceDeviceListener.class);

    private final ResourceAdminService adminService;
    private final ResourceQueryService resourceService;
    private final DeviceService deviceService;
    private final MastershipService mastershipService;
    private final DriverService driverService;
    private final NetworkConfigService netcfgService;
    private final ExecutorService executor;


    /**
     * Creates an instance with the specified ResourceAdminService and ExecutorService.
     *
     * @param adminService instance invoked to register resources
     * @param resourceService {@link ResourceQueryService} to be used
     * @param deviceService {@link DeviceService} to be used
     * @param mastershipService {@link MastershipService} to be used
     * @param driverService {@link DriverService} to be used
     * @param netcfgService {@link NetworkConfigService} to be used.
     * @param executor executor used for processing resource registration
     */
    ResourceDeviceListener(ResourceAdminService adminService, ResourceQueryService resourceService,
                           DeviceService deviceService, MastershipService mastershipService,
                           DriverService driverService, NetworkConfigService netcfgService,
                           ExecutorService executor) {
        this.adminService = checkNotNull(adminService);
        this.resourceService = checkNotNull(resourceService);
        this.deviceService = checkNotNull(deviceService);
        this.mastershipService = checkNotNull(mastershipService);
        this.driverService = checkNotNull(driverService);
        this.netcfgService = checkNotNull(netcfgService);
        this.executor = checkNotNull(executor);
    }

    @Override
    public void event(DeviceEvent event) {
        Device device = event.subject();
        // registration happens only when the caller is the master of the device
        if (!mastershipService.isLocalMaster(device.id())) {
            return;
        }

        switch (event.type()) {
            case DEVICE_ADDED:
                registerDeviceResource(device);
                break;
            case DEVICE_REMOVED:
                unregisterDeviceResource(device);
                break;
            case DEVICE_AVAILABILITY_CHANGED:
                if (deviceService.isAvailable(device.id())) {
                    registerDeviceResource(device);
                    // TODO: do we need to walk the ports?
                } else {
                    unregisterDeviceResource(device);
                }
                break;
            case PORT_ADDED:
            case PORT_UPDATED:
                if (event.port().isEnabled()) {
                    registerPortResource(device, event.port());
                } else {
                    unregisterPortResource(device, event.port());
                }
                break;
            case PORT_REMOVED:
                unregisterPortResource(device, event.port());
                break;
            default:
                break;
        }
    }

    private void registerDeviceResource(Device device) {
        executor.execute(() -> adminService.register(Resources.discrete(device.id()).resource()));
    }

    private void unregisterDeviceResource(Device device) {
        executor.execute(() -> {
            DiscreteResource devResource = Resources.discrete(device.id()).resource();
            List<Resource> allResources = getDescendantResources(devResource);
            adminService.unregister(Lists.transform(allResources, Resource::id));
        });
    }

    private void registerPortResource(Device device, Port port) {
        Resource portPath = Resources.discrete(device.id(), port.number()).resource();
        executor.execute(() -> {
            adminService.register(portPath);

            queryBandwidth(device.id(), port.number())
                .map(bw -> portPath.child(Bandwidth.class, bw.bps()))
                .map(adminService::register)
                .ifPresent(success -> {
                   if (!success) {
                       log.warn("Failed to register Bandwidth for {}", portPath.id());
                   }
                });

            // for VLAN IDs
            Set<VlanId> vlans = queryVlanIds(device.id(), port.number());
            if (!vlans.isEmpty()) {
                adminService.register(vlans.stream()
                        .map(portPath::child)
                        .collect(Collectors.toList()));
            }

            // for MPLS labels
            Set<MplsLabel> mplsLabels = queryMplsLabels(device.id(), port.number());
            if (!mplsLabels.isEmpty()) {
                adminService.register(mplsLabels.stream()
                        .map(portPath::child)
                        .collect(Collectors.toList()));
            }

            // for Lambdas
            Set<OchSignal> lambdas = queryLambdas(device.id(), port.number());
            if (!lambdas.isEmpty()) {
                adminService.register(lambdas.stream()
                        .map(portPath::child)
                        .collect(Collectors.toList()));
            }

            // for Tributary slots
            Set<TributarySlot> tSlots = queryTributarySlots(device.id(), port.number());
            if (!tSlots.isEmpty()) {
                adminService.register(tSlots.stream()
                        .map(portPath::child)
                        .collect(Collectors.toList()));
            }
        });
    }

    private void unregisterPortResource(Device device, Port port) {
        executor.execute(() -> {
            DiscreteResource portResource = Resources.discrete(device.id(), port.number()).resource();
            List<Resource> allResources = getDescendantResources(portResource);
            adminService.unregister(Lists.transform(allResources, Resource::id));
        });
    }

    // Returns list of all descendant resources of given resource, including itself.
    private List<Resource> getDescendantResources(DiscreteResource parent) {
        LinkedList<Resource> allResources = new LinkedList<>();
        allResources.add(parent);

        Set<Resource> nextResources = resourceService.getRegisteredResources(parent.id());
        while (!nextResources.isEmpty()) {
            Set<Resource> currentResources = nextResources;
            // resource list should be ordered from leaf to root
            allResources.addAll(0, currentResources);

            nextResources = currentResources.stream()
                    .filter(r -> r instanceof DiscreteResource)
                    .map(r -> (DiscreteResource) r)
                    .flatMap(r -> resourceService.getRegisteredResources(r.id()).stream())
                    .collect(Collectors.toSet());
        }

        return allResources;
    }

    /**
     * Query bandwidth capacity on a port.
     *
     * @param did {@link DeviceId}
     * @param number {@link PortNumber}
     * @return bandwidth capacity
     */
    private Optional<Bandwidth> queryBandwidth(DeviceId did, PortNumber number) {
        // Check and use netcfg first.
        ConnectPoint cp = new ConnectPoint(did, number);
        BandwidthCapacity config = netcfgService.getConfig(cp, BandwidthCapacity.class);
        if (config != null) {
            log.trace("Registering configured bandwidth {} for {}/{}", config.capacity(), did, number);
            return Optional.of(config.capacity());
        }

        // populate bandwidth value, assuming portSpeed == bandwidth
        Port port = deviceService.getPort(did, number);
        if (port != null) {
            return Optional.of(Bandwidth.mbps(port.portSpeed()));
        }
        return Optional.empty();
    }

    private Set<OchSignal> queryLambdas(DeviceId did, PortNumber port) {
        try {
            DriverHandler handler = driverService.createHandler(did);
            if (handler == null || !handler.hasBehaviour(LambdaQuery.class)) {
                return Collections.emptySet();
            }
            LambdaQuery query = handler.behaviour(LambdaQuery.class);
            if (query != null) {
                return query.queryLambdas(port).stream()
                        .flatMap(ResourceDeviceListener::toResourceGrid)
                        .collect(Collectors.toSet());
            } else {
                return Collections.emptySet();
            }
        } catch (ItemNotFoundException e) {
            return Collections.emptySet();
        }
    }

    /**
     * Convert {@link OchSignal} into gridtype used to track Resource.
     *
     * @param ochSignal {@link OchSignal}
     * @return {@code ochSignal} mapped to Stream of flex grid slots with 6.25 GHz spacing
     *         and 12.5 GHz slot width.
     */
    private static Stream<OchSignal> toResourceGrid(OchSignal ochSignal) {
        if (ochSignal.gridType() != GridType.FLEX) {
            return OchSignal.toFlexGrid(ochSignal).stream();
        }
        if (ochSignal.gridType() == GridType.FLEX &&
            ochSignal.channelSpacing() == ChannelSpacing.CHL_6P25GHZ &&
            ochSignal.slotGranularity() == 1) {
                // input was already flex grid slots with 6.25 GHz spacing and 12.5 GHz slot width.
                return Stream.of(ochSignal);
        }
        // FIXME handle FLEX but not 6.25 GHz spacing or 12.5 GHz slot width case.
        log.error("Converting {} to resource tracking grid not supported yet.", ochSignal);
        return Stream.<OchSignal>builder().build();
    }

    private Set<VlanId> queryVlanIds(DeviceId device, PortNumber port) {
        try {
            DriverHandler handler = driverService.createHandler(device);
            if (handler == null || !handler.hasBehaviour(VlanQuery.class)) {
                return ImmutableSet.of();
            }

            VlanQuery query = handler.behaviour(VlanQuery.class);
            if (query == null) {
                return ImmutableSet.of();
            }
            return query.queryVlanIds(port);
        } catch (ItemNotFoundException e) {
            return ImmutableSet.of();
        }
    }

    private Set<MplsLabel> queryMplsLabels(DeviceId device, PortNumber port) {
        try {
            DriverHandler handler = driverService.createHandler(device);
            if (handler == null || !handler.hasBehaviour(MplsQuery.class)) {
                return ImmutableSet.of();
            }

            MplsQuery query = handler.behaviour(MplsQuery.class);
            if (query == null) {
                return ImmutableSet.of();
            }
            return query.queryMplsLabels(port);
        } catch (ItemNotFoundException e) {
            return ImmutableSet.of();
        }
    }

    private Set<TributarySlot> queryTributarySlots(DeviceId device, PortNumber port) {
        try {
            DriverHandler handler = driverService.createHandler(device);
            if (handler == null || !handler.hasBehaviour(TributarySlotQuery.class)) {
                return Collections.emptySet();
            }
            TributarySlotQuery query = handler.behaviour(TributarySlotQuery.class);
            if (query != null) {
                return query.queryTributarySlots(port);
            } else {
                return Collections.emptySet();
            }
        } catch (ItemNotFoundException e) {
            return Collections.emptySet();
        }
    }
}
