/*
 * 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.optical.intent.impl.compiler;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
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.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.util.Frequency;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultOchSignalComparator;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.Path;
import org.onosproject.net.Port;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.OpticalConnectivityIntent;
import org.onosproject.net.intent.OpticalPathIntent;
import org.onosproject.net.optical.OchPort;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.Resource;
import org.onosproject.net.resource.ResourceService;
import org.onosproject.net.resource.Resources;
import org.onosproject.net.topology.AdapterLinkWeigher;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyEdge;
import org.onosproject.net.topology.TopologyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.google.common.base.Preconditions.checkArgument;
import static org.onosproject.net.OchSignal.toFlexGrid;
import static org.onosproject.net.optical.device.OpticalDeviceServiceView.opticalView;

/**
 * An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}.
 */
@Component(immediate = true)
public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {

    protected static final Logger log = LoggerFactory.getLogger(OpticalConnectivityIntentCompiler.class);
    // By default, allocate 50 GHz lambdas (4 slots of 12.5 GHz) for each intent.
    private static final int SLOT_COUNT = 4;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected IntentExtensionService intentManager;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected TopologyService topologyService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ResourceService resourceService;

    @Activate
    public void activate() {
        deviceService = opticalView(deviceService);
        intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
    }

    @Deactivate
    public void deactivate() {
        intentManager.unregisterCompiler(OpticalConnectivityIntent.class);
    }

    @Override
    public List<Intent> compile(OpticalConnectivityIntent intent,
                                List<Intent> installable) {
        // Check if source and destination are optical OCh ports
        ConnectPoint src = intent.getSrc();
        ConnectPoint dst = intent.getDst();
        Port srcPort = deviceService.getPort(src.deviceId(), src.port());
        Port dstPort = deviceService.getPort(dst.deviceId(), dst.port());
        checkArgument(srcPort instanceof OchPort);
        checkArgument(dstPort instanceof OchPort);

        log.debug("Compiling optical connectivity intent between {} and {}", src, dst);

        // Release of intent resources here is only a temporary solution for handling the
        // case of recompiling due to intent restoration (when intent state is FAILED).
        // TODO: try to release intent resources in IntentManager.
        resourceService.release(intent.key());

        // Check OCh port availability
        Resource srcPortResource = Resources.discrete(src.deviceId(), src.port()).resource();
        Resource dstPortResource = Resources.discrete(dst.deviceId(), dst.port()).resource();
        // If ports are not available, compilation fails
        if (!Stream.of(srcPortResource, dstPortResource).allMatch(resourceService::isAvailable)) {
            throw new OpticalIntentCompilationException("Ports for the intent are not available. Intent: " + intent);
        }

        List<Resource> resources = new ArrayList<>();
        resources.add(srcPortResource);
        resources.add(dstPortResource);

        // Calculate available light paths
        Stream<Path> paths = getOpticalPaths(intent);

        // Static or dynamic lambda allocation
        String staticLambda = srcPort.annotations().value(AnnotationKeys.STATIC_LAMBDA);
        OchPort srcOchPort = (OchPort) srcPort;
        OchPort dstOchPort = (OchPort) dstPort;

        // FIXME: need to actually reserve the lambda for static lambda's
        // static lambda case: early return
        if (staticLambda != null) {

            OchSignal lambda = new OchSignal(Frequency.ofHz(Long.parseLong(staticLambda)),
                                             srcOchPort.lambda().channelSpacing(),
                                             srcOchPort.lambda().slotGranularity());
            log.debug("Using staticalluy assigned lambda : {}", lambda);

            List<Resource> res = new ArrayList<>();

            Path satPath = paths.filter(path -> {
                // FIXME trimming both ends (staticLambda assigned ports)
                // Proper fix is to let device advertise static lambda as resource.
                LinkedList<Link> links = new LinkedList<>(path.links());
                links.pollFirst();
                links.pollLast();

                List<Resource> r = convertToResources(links, toFlexGrid(lambda));
                if (r.stream().allMatch(resourceService::isAvailable)) {
                    // FIXME bad practice to have side-effect during stream
                    res.addAll(r);
                    return true;
                }
                return false;
            }).findFirst().orElse(null);

            if (satPath == null) {
                // FIXME doing something very wrong to preserve old behavior
                // as a fallback
                log.warn("No feasible path between {}-{} using {}",
                         src, dst, lambda);

                satPath = getOpticalPaths(intent).iterator().next();
                if (satPath == null) {
                    throw new OpticalIntentCompilationException(
                        "Unable to find suitable lightpath for intent " + intent);
                }
                return ImmutableList.of(createIntent(intent, satPath, lambda));
            }

            resources.addAll(res);
            allocateResources(intent, resources);

            return ImmutableList.of(createIntent(intent, satPath, lambda));
        }

        // FIXME: also check destination OCh port
        // non-tunable case: early return
        if (!srcOchPort.isTunable() || !dstOchPort.isTunable()) {
            Path firstPath = paths.findAny().orElse(null);
            if (firstPath == null) {
                throw new OpticalIntentCompilationException("Unable to find suitable lightpath for intent " + intent);
            }
            OchSignal lambda = srcOchPort.lambda();
            // TODO apply the same as static lambda case above
            // - pick feasible path
            // - allocate resources
            //resources.addAll(convertToResources(firstPath.links(), toFlexGrid(lambda)));
            allocateResources(intent, resources);
            return ImmutableList.of(createIntent(intent, firstPath, lambda));
        }

        // remaining cases
        // Use first path that the required resources are available
        Optional<Map.Entry<Path, List<OchSignal>>> found = paths
                .map(path -> Maps.immutableEntry(path, findFirstAvailableOch(path)))
                .filter(entry -> !entry.getValue().isEmpty())
                .filter(entry -> convertToResources(entry.getKey().links(),
                        entry.getValue()).stream().allMatch(resourceService::isAvailable))
                .findFirst();

        if (found.isPresent()) {
            resources.addAll(convertToResources(found.get().getKey().links(), found.get().getValue()));

            allocateResources(intent, resources);

            OchSignal ochSignal = OchSignal.toFixedGrid(found.get().getValue(), ChannelSpacing.CHL_50GHZ);
            return ImmutableList.of(createIntent(intent, found.get().getKey(), ochSignal));
        } else {
            throw new OpticalIntentCompilationException("Unable to find suitable lightpath for intent " + intent);
        }
    }

    private Intent createIntent(OpticalConnectivityIntent parentIntent, Path path, OchSignal lambda) {
        // Create installable optical path intent
        // Only support fixed grid for now
        OchSignalType signalType = OchSignalType.FIXED_GRID;

        return OpticalPathIntent.builder()
                .appId(parentIntent.appId())
                .key(parentIntent.key())
                .src(parentIntent.getSrc())
                .dst(parentIntent.getDst())
                .path(path)
                .lambda(lambda)
                .signalType(signalType)
                .bidirectional(parentIntent.isBidirectional())
                .resourceGroup(parentIntent.resourceGroup())
                .build();
    }

    private void allocateResources(Intent intent, List<Resource> resources) {
        // reserve all of required resources
        List<ResourceAllocation> allocations = resourceService.allocate(intent.key(), resources);
        if (allocations.isEmpty()) {
            log.error("Resource allocation for {} failed (resource request: {})", intent.key(), resources);
            if (log.isDebugEnabled()) {
                log.debug("requested resources:\n\t{}", resources.stream()
                                  .map(Resource::toString)
                                  .collect(Collectors.joining("\n\t")));
            }
            throw new OpticalIntentCompilationException("Unable to allocate resources: " + resources);
        }
    }

    private List<OchSignal> findFirstAvailableOch(Path path) {
        Set<OchSignal> lambdas = findCommonLambdasOverLinks(path.links());
        if (lambdas.isEmpty()) {
            return Collections.emptyList();
        }

        return findFirstLambda(lambdas, slotCount());
    }

    private List<Resource> convertToResources(List<Link> links, Collection<OchSignal> lambda) {
        return links.stream()
                .flatMap(x -> Stream.of(
                        Resources.discrete(x.src().deviceId(), x.src().port()).resource(),
                        Resources.discrete(x.dst().deviceId(), x.dst().port()).resource()
                ))
                .flatMap(x -> lambda.stream().map(x::child))
                .collect(Collectors.toList());
    }

    /**
     * Get the number of 12.5 GHz slots required for the path.
     *
     * For now this returns a constant value of 4 (i.e., fixed grid 50 GHz slot),
     * but in the future can depend on optical reach, line rate, transponder port capabilities, etc.
     *
     * @return number of slots
     */
    private int slotCount() {
        return SLOT_COUNT;
    }

    private Set<OchSignal> findCommonLambdasOverLinks(List<Link> links) {
        return links.stream()
                .flatMap(x -> Stream.of(
                        Resources.discrete(x.src().deviceId(), x.src().port()).id(),
                        Resources.discrete(x.dst().deviceId(), x.dst().port()).id()
                ))
                .map(x -> resourceService.getAvailableResourceValues(x, OchSignal.class))
                .map(x -> (Set<OchSignal>) ImmutableSet.copyOf(x))
                .reduce(Sets::intersection)
                .orElse(Collections.emptySet());
    }

    /**
     * Returns list of consecutive resources in given set of lambdas.
     *
     * @param lambdas list of lambdas
     * @param count number of consecutive lambdas to return
     * @return list of consecutive lambdas
     */
    private List<OchSignal> findFirstLambda(Set<OchSignal> lambdas, int count) {
        // Sort available lambdas
        List<OchSignal> lambdaList = new ArrayList<>(lambdas);
        lambdaList.sort(new DefaultOchSignalComparator());

        // Look ahead by count and ensure spacing multiplier is as expected (i.e., no gaps)
        for (int i = 0; i < lambdaList.size() - count; i++) {
            if (lambdaList.get(i).spacingMultiplier() + 2 * count ==
                    lambdaList.get(i + count).spacingMultiplier()) {
                return lambdaList.subList(i, i + count);
            }
        }

        return Collections.emptyList();
    }

    private ConnectPoint staticPort(ConnectPoint connectPoint) {
        Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());

        String staticPort = port.annotations().value(AnnotationKeys.STATIC_PORT);

        // FIXME: need a better way to match the port
        if (staticPort != null) {
            for (Port p : deviceService.getPorts(connectPoint.deviceId())) {
                if (staticPort.equals(p.number().name())) {
                    return new ConnectPoint(p.element().id(), p.number());
                }
            }
        }

        return null;
    }

    /**
     * Calculates optical paths in WDM topology.
     *
     * @param intent optical connectivity intent
     * @return set of paths in WDM topology
     */
    private Stream<Path> getOpticalPaths(OpticalConnectivityIntent intent) {
        // Route in WDM topology
        Topology topology = topologyService.currentTopology();
        LinkWeight weight = new LinkWeight() {

            @Override
            public double weight(TopologyEdge edge) {
                // Disregard inactive or non-optical links
                if (edge.link().state() == Link.State.INACTIVE) {
                    return -1;
                }
                if (edge.link().type() != Link.Type.OPTICAL) {
                    return -1;
                }
                // Adhere to static port mappings
                DeviceId srcDeviceId = edge.link().src().deviceId();
                if (srcDeviceId.equals(intent.getSrc().deviceId())) {
                    ConnectPoint srcStaticPort = staticPort(intent.getSrc());
                    if (srcStaticPort != null) {
                        return srcStaticPort.equals(edge.link().src()) ? 1 : -1;
                    }
                }
                DeviceId dstDeviceId = edge.link().dst().deviceId();
                if (dstDeviceId.equals(intent.getDst().deviceId())) {
                    ConnectPoint dstStaticPort = staticPort(intent.getDst());
                    if (dstStaticPort != null) {
                        return dstStaticPort.equals(edge.link().dst()) ? 1 : -1;
                    }
                }

                return 1;
            }
        };

        ConnectPoint start = intent.getSrc();
        ConnectPoint end = intent.getDst();
        Stream<Path> paths = topologyService.getKShortestPaths(topology,
                                                            start.deviceId(),
                                                            end.deviceId(),
                                                            AdapterLinkWeigher.adapt(weight));
        if (log.isDebugEnabled()) {
            return paths
                    .map(path -> {
                        // no-op map stage to add debug logging
                        log.debug("Candidate path: {}",
                                  path.links().stream()
                                      .map(lk -> lk.src() + "-" + lk.dst())
                                      .collect(Collectors.toList()));
                        return path;
                    });
        }
        return paths;
    }
}
