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


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.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.LinkKey;
import org.onosproject.net.OduSignalId;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.OduSignalUtils;
import org.onosproject.net.Path;
import org.onosproject.net.Port;
import org.onosproject.net.TributarySlot;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.OpticalOduIntent;
import org.onosproject.net.intent.impl.IntentCompilationException;
import org.onosproject.net.optical.OduCltPort;
import org.onosproject.net.optical.OtuPort;
import org.onosproject.net.resource.Resource;
import org.onosproject.net.resource.ResourceService;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.Resources;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
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.LinkKey.linkKey;
import static org.onosproject.net.optical.device.OpticalDeviceServiceView.opticalView;

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

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

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

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

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

    private ApplicationId appId;

    @Activate
    public void activate() {
        deviceService = opticalView(deviceService);
        appId = coreService.registerApplication("org.onosproject.net.intent");
        intentManager.registerCompiler(OpticalOduIntent.class, this);
    }

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

    @Override
    public List<Intent> compile(OpticalOduIntent intent, List<Intent> installable) {
        // Check if ports are OduClt 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 OduCltPort);
        checkArgument(dstPort instanceof OduCltPort);

        log.debug("Compiling optical ODU 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.id());

        // Check OduClt ports 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 IntentCompilationException("Ports for the intent are not available. Intent: " + intent);
        }
        List<Resource> intentResources = new ArrayList<>();
        intentResources.add(srcPortResource);
        intentResources.add(dstPortResource);

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

        if (paths.isEmpty()) {
            throw new IntentCompilationException("Unable to find suitable lightpath for intent " + intent);
        }

        // Use first path that can be successfully reserved
        for (Path path : paths) {

            // Find available Tributary Slots on both directions of path
            Map<LinkKey, Set<TributarySlot>> slotsMap = findAvailableTributarySlots(intent, path);
            if (slotsMap.isEmpty()) {
                continue;
            }
            List<Resource> tributarySlotResources = convertToResources(slotsMap);
            if (!tributarySlotResources.stream().allMatch(resourceService::isAvailable)) {
                continue;
            }

            intentResources.addAll(tributarySlotResources);

            allocateResources(intent, intentResources);

            List<FlowRule> rules = new LinkedList<>();

            // Create rules for forward and reverse path
            rules = createRules(intent, intent.getSrc(), intent.getDst(), path, slotsMap, false);
            if (intent.isBidirectional()) {
                rules.addAll(createRules(intent, intent.getDst(), intent.getSrc(), path, slotsMap, true));
            }

            return Collections.singletonList(new FlowRuleIntent(appId,
                    rules, ImmutableSet.copyOf(path.links())));
        }

        throw new IntentCompilationException("Unable to find suitable lightpath for intent " + intent);
    }

    /**
     * Find available TributarySlots across path.
     *
     * @param intent
     * @param path path in OTU topology
     * @return Map of Linkey and Set of available TributarySlots on its ports
     */
    private Map<LinkKey, Set<TributarySlot>> findAvailableTributarySlots(OpticalOduIntent intent, Path path) {
        Set<LinkKey> linkRequest = Sets.newHashSetWithExpectedSize(path.links().size());
        for (int i = 0; i < path.links().size(); i++) {
            LinkKey link = linkKey(path.links().get(i));
            linkRequest.add(link);
        }

        return findTributarySlots(intent, linkRequest);
    }

    private List<Resource> convertToResources(Map<LinkKey, Set<TributarySlot>> slotsMap) {
       // Same TributarySlots are used for both directions
        Set<Resource> resources = slotsMap.entrySet().stream()
                .flatMap(x -> x.getValue()
                        .stream()
                        .flatMap(ts-> Stream.of(
                                Resources.discrete(x.getKey().src().deviceId(), x.getKey().src().port())
                                        .resource().child(ts),
                                Resources.discrete(x.getKey().dst().deviceId(), x.getKey().dst().port())
                                        .resource().child(ts))))
                .collect(Collectors.toSet());
        return (ImmutableList.copyOf(resources));
    }

    private void allocateResources(Intent intent, List<Resource> resources) {
        // reserve all of required resources
        List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), resources);
        if (allocations.isEmpty()) {
            log.info("Resource allocation for {} failed (resource request: {})", intent, resources);
            throw new IntentCompilationException("Unable to allocate resources: " + resources);
        }
    }

    private Map<LinkKey, Set<TributarySlot>> findTributarySlots(OpticalOduIntent intent, Set<LinkKey> links) {
        OduSignalType oduSignalType = OduSignalUtils.mappingCltSignalTypeToOduSignalType(intent.getSignalType());
        int requestedTsNum = oduSignalType.tributarySlots();

        Map<LinkKey, Set<TributarySlot>> slotsMap = new HashMap<>();
        for (LinkKey link : links) {
            Set<TributarySlot> common = findCommonTributarySlotsOnCps(link.src(), link.dst());
            if (common.isEmpty() || (common.size() < requestedTsNum)) {
                log.debug("Failed to find TributarySlots on link {} requestedTsNum={}", link, requestedTsNum);
                return Collections.emptyMap(); // failed to find enough available TributarySlots on a link
            }
            slotsMap.put(link, common.stream()
                                .limit(requestedTsNum)
                                .collect(Collectors.toSet()));
        }
        return slotsMap;
    }

    /**
     * Calculates optical paths in OTU topology.
     *
     * @param intent optical ODU intent
     * @return set of paths in OTU topology
     */
    private Set<Path> getOpticalPaths(OpticalOduIntent intent) {
        // Route in OTU topology
        Topology topology = topologyService.currentTopology();

        LinkWeight weight = 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;
            }
            // Find path with available TributarySlots resources
            if (!isAvailableTributarySlots(intent, edge.link())) {
                return -1;
            }
            return 1;
        };

        ConnectPoint start = intent.getSrc();
        ConnectPoint end = intent.getDst();

        return topologyService.getPaths(topology, start.deviceId(), end.deviceId(), weight);
    }

    private boolean isAvailableTributarySlots(OpticalOduIntent intent, Link link) {
        OduSignalType oduSignalType = OduSignalUtils.mappingCltSignalTypeToOduSignalType(intent.getSignalType());
        int requestedTsNum = oduSignalType.tributarySlots();

        Set<TributarySlot> common = findCommonTributarySlotsOnCps(link.src(), link.dst());
        if (common.isEmpty() || (common.size() < requestedTsNum)) {
            log.debug("Not enough available TributarySlots on link {} requestedTsNum={}", link, requestedTsNum);
            return false;
        }
        return true;
    }

    /**
     * Create rules for the forward (or the reverse) path of the intent.
     *
     * @param intent OpticalOduIntent intent
     * @param path path found for intent
     * @param slotsMap Map of LinkKey and TributarySlots resources
     * @return list of flow rules
     */
    private List<FlowRule> createRules(OpticalOduIntent intent, ConnectPoint src, ConnectPoint dst,
            Path path, Map<LinkKey, Set<TributarySlot>> slotsMap, boolean reverse) {
        // Build the ingress OTN rule
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.matchInPort(src.port());
        OduSignalType oduCltPortOduSignalType =
                OduSignalUtils.mappingCltSignalTypeToOduSignalType(intent.getSignalType());
        selector.add(Criteria.matchOduSignalType(oduCltPortOduSignalType));

        List<FlowRule> rules = new LinkedList<>();
        ConnectPoint current = src;

        List<Link> links = ((!reverse) ? path.links() : Lists.reverse(path.links()));

        for (Link link : links) {
            Set<TributarySlot> slots = slotsMap.get(linkKey(link));
            OtuPort otuPort = (OtuPort) (deviceService.getPort(link.src().deviceId(), link.src().port()));
            OduSignalType otuPortOduSignalType =
                    OduSignalUtils.mappingOtuSignalTypeToOduSignalType(otuPort.signalType());

            TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
            OduSignalId oduSignalId = null;
            // use Instruction of OduSignalId only in case of ODU Multiplexing
            if (oduCltPortOduSignalType != otuPortOduSignalType) {
                oduSignalId = OduSignalUtils.buildOduSignalId(otuPortOduSignalType, slots);
                treat.add(Instructions.modL1OduSignalId(oduSignalId));
            }
            ConnectPoint next = ((!reverse) ? link.src() : link.dst());
            treat.setOutput(next.port());

            FlowRule rule = createFlowRule(intent, current.deviceId(), selector.build(), treat.build());
            rules.add(rule);

            current = ((!reverse) ? link.dst() : link.src());
            selector = DefaultTrafficSelector.builder();
            selector.matchInPort(current.port());
            selector.add(Criteria.matchOduSignalType(oduCltPortOduSignalType));
            // use Criteria of OduSignalId only in case of ODU Multiplexing
            if (oduCltPortOduSignalType != otuPortOduSignalType) {
                selector.add(Criteria.matchOduSignalId(oduSignalId));
            }
        }

        // Build the egress OTN rule
        TrafficTreatment.Builder treatLast = DefaultTrafficTreatment.builder();
        treatLast.setOutput(dst.port());

        FlowRule rule = createFlowRule(intent, dst.deviceId(), selector.build(), treatLast.build());
        rules.add(rule);

        return rules;
    }

    private FlowRule createFlowRule(OpticalOduIntent intent, DeviceId deviceId,
            TrafficSelector selector, TrafficTreatment treat) {
        return DefaultFlowRule.builder()
                .forDevice(deviceId)
                .withSelector(selector)
                .withTreatment(treat)
                .withPriority(intent.priority())
                .fromApp(appId)
                .makePermanent()
                .build();
    }

    /**
     * Finds the common TributarySlots available on the two connect points.
     *
     * @param src source connect point
     * @param dst dest connect point
     * @return set of common TributarySlots on both connect points
     */
    Set<TributarySlot> findCommonTributarySlotsOnCps(ConnectPoint src, ConnectPoint dst) {
        Set<TributarySlot> forward = findTributarySlotsOnCp(src);
        Set<TributarySlot> backward = findTributarySlotsOnCp(dst);
        return Sets.intersection(forward, backward);
    }

    /**
     * Finds the TributarySlots available on the connect point.
     *
     * @param cp connect point
     * @return set of TributarySlots available on the connect point
     */
    Set<TributarySlot> findTributarySlotsOnCp(ConnectPoint cp) {
        return resourceService.getAvailableResourceValues(
                Resources.discrete(cp.deviceId(), cp.port()).id(),
                TributarySlot.class);
    }
}