/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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 static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Lists.transform;
import static java.util.stream.Stream.concat;
import static org.onosproject.net.MarkerResource.marker;
import static org.onosproject.net.behaviour.protection.ProtectedTransportEndpointDescription.buildDescription;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.tuple.Pair;
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.packet.VlanId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.DeviceId;
import org.onosproject.net.DisjointPath;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.Link;
import org.onosproject.net.Link.State;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.Path;
import org.onosproject.net.behaviour.protection.TransportEndpointDescription;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompilationException;
import org.onosproject.net.intent.LinkCollectionIntent;
import org.onosproject.net.intent.ProtectedTransportIntent;
import org.onosproject.net.intent.ProtectionEndpointIntent;
import org.onosproject.net.resource.DiscreteResourceId;
import org.onosproject.net.resource.Resource;
import org.onosproject.net.resource.ResourceService;
import org.onosproject.net.resource.Resources;
import org.slf4j.Logger;

import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

/**
 * IntentCompiler for {@link ProtectedTransportIntent}.
 */
@Beta
@Component(immediate = true)
public class ProtectedTransportIntentCompiler
        extends ConnectivityIntentCompiler<ProtectedTransportIntent> {

    /**
     * Marker value for forward path.
     */
    private static final String FWD = "fwd";

    /**
     * Marker value for reverse path.
     */
    private static final String REV = "rev";


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

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

    @Activate
    public void activate() {
        intentManager.registerCompiler(ProtectedTransportIntent.class, this);
        log.info("started");
    }

    @Deactivate
    public void deactivate() {
        intentManager.unregisterCompiler(ProtectedTransportIntent.class);
        log.info("stopped");
    }

    @Override
    public List<Intent> compile(ProtectedTransportIntent intent,
                                List<Intent> installable) {
        log.trace("compiling {} {}", intent, installable);

        // case 0 hop, same device
        final DeviceId did1 = intent.one();
        final DeviceId did2 = intent.two();
        if (Objects.equals(did1, did2)) {
            // Doesn't really make sense to create 0 hop protected path, but
            // can generate Flow for the device, just to provide connectivity.
            // future work.
            log.error("0 hop not supported yet.");
            throw new IntentCompilationException("0 hop not supported yet.");
        }

        List<Intent> reusable = Optional.ofNullable(installable).orElse(ImmutableList.of())
            .stream()
            .filter(this::isIntact)
            .collect(Collectors.toList());
        if (reusable.isEmpty() ||
            reusable.stream().allMatch(ProtectionEndpointIntent.class::isInstance)) {
            // case provisioning new protected path
            //   or
            // case re-compilation (total failure -> restoration)
            return createFreshProtectedPaths(intent, did1, did2);
        } else {
            // case re-compilation (partial failure)
            log.warn("Re-computing adding new backup path not supported yet. No-Op.");
            // TODO This part needs to be flexible to support various use case
            // - non-revertive behavior (Similar to PartialFailureConstraint)
            // - revertive behavior
            // - compute third path
            // ...
            //  Require further input what they actually need.

            // TODO handle PartialFailureConstraint

            /// case only need to update transit portion
            /// case head and/or tail needs to be updated

            // TODO do we need to prune broken
            return installable;
        }
    }

    /**
     * Test if resources used by specified Intent is intact.
     *
     * @param installed Intent to test
     * @return true if Intent is intact
     */
    private boolean isIntact(Intent installed) {
        return installed.resources().stream()
            .filter(Link.class::isInstance)
            .map(Link.class::cast)
            .allMatch(this::isLive);
    }

    /**
     * Test if specified Link is intact.
     *
     * @param link to test
     * @return true if link is intact
     */
    private boolean isLive(Link link) {
        // Only testing link state for now
        // in the long run, consider verifying OAM state on ports
        return link.state() != State.INACTIVE;
    }

    /**
     * Creates new protected paths.
     *
     * @param intent    original intention
     * @param did1      identifier of first device
     * @param did2      identifier of second device
     * @return compilation result
     * @throws IntentCompilationException when there's no satisfying path.
     */
    private List<Intent> createFreshProtectedPaths(ProtectedTransportIntent intent,
                                                   DeviceId did1,
                                                   DeviceId did2) {
        DisjointPath disjointPath = getDisjointPath(intent, did1, did2);
        if (disjointPath == null || disjointPath.backup() == null) {
            log.error("Unable to find disjoint path between {}, {}", did1, did2);
            throw new IntentCompilationException("Unable to find disjoint paths.");
        }
        Path primary = disjointPath.primary();
        Path secondary = disjointPath.backup();

        String fingerprint = intent.key().toString();

        // pick and allocate Vlan to use as S-tag
        Pair<VlanId, VlanId> vlans = allocateEach(intent, primary, secondary, VlanId.class);

        VlanId primaryVlan = vlans.getLeft();
        VlanId secondaryVlan = vlans.getRight();

        // Build edge Intents for head/tail

        // resource for head/tail
        Collection<NetworkResource> oneResources = new ArrayList<>();
        Collection<NetworkResource> twoResources = new ArrayList<>();

        List<TransportEndpointDescription> onePaths = new ArrayList<>();
        onePaths.add(TransportEndpointDescription.builder()
                         .withOutput(vlanPort(primary.src(), primaryVlan))
                         .build());
        onePaths.add(TransportEndpointDescription.builder()
                         .withOutput(vlanPort(secondary.src(), secondaryVlan))
                         .build());

        List<TransportEndpointDescription> twoPaths = new ArrayList<>();
        twoPaths.add(TransportEndpointDescription.builder()
                     .withOutput(vlanPort(primary.dst(), primaryVlan))
                     .build());
        twoPaths.add(TransportEndpointDescription.builder()
                     .withOutput(vlanPort(secondary.dst(), secondaryVlan))
                     .build());

        ProtectionEndpointIntent oneIntent = ProtectionEndpointIntent.builder()
                .key(intent.key())
                .appId(intent.appId())
                .priority(intent.priority())
                .resources(oneResources)
                .deviceId(did1)
                .description(buildDescription(onePaths, did2, fingerprint))
                .build();
        ProtectionEndpointIntent twoIntent = ProtectionEndpointIntent.builder()
                .key(intent.key())
                .appId(intent.appId())
                .resources(twoResources)
                .deviceId(did2)
                .description(buildDescription(twoPaths, did1, fingerprint))
                .build();

        // Build transit intent for primary/secondary path

        Collection<NetworkResource> resources1 = ImmutableList.of(marker("protection1"));
        Collection<NetworkResource> resources2 = ImmutableList.of(marker("protection2"));

        ImmutableList<Intent> result = ImmutableList.<Intent>builder()
                // LinkCollection for primary and backup paths
                .addAll(createTransitIntent(intent, primary, primaryVlan, resources1))
                .addAll(createTransitIntent(intent, secondary, secondaryVlan, resources2))
                .add(oneIntent)
                .add(twoIntent)
                .build();
        log.trace("createFreshProtectedPaths result: {}", result);
        return result;
    }

    /**
     * Creates required Intents required to transit bi-directionally the network.
     *
     * @param intent parent IntentId
     * @param path whole path
     * @param vid VlanId to use as tunnel labels
     * @param resources to be passed down to generated Intents
     * @return List on transit Intents, if any is required.
     */
    List<LinkCollectionIntent> createTransitIntent(Intent intent,
                                                   Path path,
                                                   VlanId vid,
                                                   Collection<NetworkResource> resources) {
        if (path.links().size() <= 1) {
            // There's no need for transit Intents
            return ImmutableList.of();
        }

        Collection<NetworkResource> fwd = ImmutableList.<NetworkResource>builder()
                                            .addAll(resources)
                                            .add(marker(FWD))
                                            .build();
        Collection<NetworkResource> rev = ImmutableList.<NetworkResource>builder()
                                            .addAll(resources)
                                            .add(marker(REV))
                                            .build();

        return ImmutableList.of(createSubTransitIntent(intent, path, vid, fwd),
                                createSubTransitIntent(intent, reverse(path), vid, rev));
    }

    /**
     * Returns a path in reverse direction.
     *
     * @param path to reverse
     * @return reversed path
     */
    Path reverse(Path path) {
        List<Link> revLinks = Lists.reverse(transform(path.links(), this::reverse));
        return new DefaultPath(path.providerId(),
                               revLinks,
                               path.weight(),
                               path.annotations());
    }

    // TODO consider adding equivalent to Link/DefaultLink.
    /**
     * Returns a link in reverse direction.
     *
     * @param link to revese
     * @return reversed link
     */
    Link reverse(Link link) {
        return DefaultLink.builder()
                .providerId(link.providerId())
                .src(link.dst())
                .dst(link.src())
                .type(link.type())
                .state(link.state())
                .isExpected(link.isExpected())
                .annotations(link.annotations())
                .build();
    }

    /**
     * Creates required Intents required to transit uni-directionally along the Path.
     *
     * @param intent parent IntentId
     * @param path whole path
     * @param vid VlanId to use as tunnel labels
     * @param resources to be passed down to generated Intents
     * @return List of transit Intents, if any is required.
     */
    LinkCollectionIntent createSubTransitIntent(Intent intent,
                                                Path path,
                                                VlanId vid,
                                                Collection<NetworkResource> resources) {
        checkArgument(path.links().size() > 1);

        // transit ingress/egress
        ConnectPoint one = path.links().get(0).dst();
        ConnectPoint two = path.links().get(path.links().size() - 1).src();

        return LinkCollectionIntent.builder()
                    // TODO there should probably be .parent(intent)
                    // which copies key, appId, priority, ...
                    .key(intent.key())
                    .appId(intent.appId())
                    .priority(intent.priority())
                    //.constraints(intent.constraints())
                    // VLAN tunnel
                    //.selector(DefaultTrafficSelector.builder().matchVlanId(vid).build())
                    //.treatment(intent.treatment())
                    .resources(resources)
                    .links(ImmutableSet.copyOf(path.links()))
                    .filteredIngressPoints(ImmutableSet.of(vlanPort(one, vid)))
                    .filteredEgressPoints(ImmutableSet.of(vlanPort(two, vid)))
                    // magic flag required for p2p type
                    .applyTreatmentOnEgress(true)
                    .cost(path.cost())
                    .build();
    }

    /**
     * Creates VLAN filtered-ConnectPoint.
     *
     * @param cp  ConnectPoint
     * @param vid VLAN ID
     * @return filtered-ConnectPoint
     */
    static FilteredConnectPoint vlanPort(ConnectPoint cp, VlanId vid) {
        return new FilteredConnectPoint(cp, DefaultTrafficSelector.builder()
                                        .matchVlanId(vid)
                                        .build());
    }

    /**
     * Creates ResourceId for a port.
     *
     * @param cp ConnectPoint
     * @return ResourceId
     */
    static DiscreteResourceId resourceId(ConnectPoint cp) {
        return Resources.discrete(cp.deviceId(), cp.port()).id();
    }

    /**
     * Allocate resource for each {@link Path}s.
     *
     * @param intent to allocate resource to
     * @param primary path
     * @param secondary path
     * @param klass label resource class
     * @return Pair of chosen resource (primary, secondary)
     * @param <T> label resource type
     * @throws IntentCompilationException when there is no resource available
     */
    <T> Pair<T, T> allocateEach(Intent intent, Path primary, Path secondary, Class<T> klass) {
        log.trace("allocateEach({}, {}, {}, {})", intent, primary, secondary, klass);
        Pair<T, T> vlans = null;
        do {
            Set<T> primaryVlans = commonLabelResource(primary, klass);
            Set<T> secondaryVlans = commonLabelResource(secondary, klass);
            Pair<T, T> candidates = pickEach(primaryVlans, secondaryVlans);
            T primaryT = candidates.getLeft();
            T secondaryT = candidates.getRight();

            // try to allocate candidates along each path
            Stream<Resource> primaryResources = primary.links().stream()
                    .flatMap(link -> Stream.of(link.src(), link.dst()))
                    .distinct()
                    .map(cp -> Resources.discrete(resourceId(cp), primaryT).resource());
            Stream<Resource> secondaryResources = secondary.links().stream()
                    .flatMap(link -> Stream.of(link.src(), link.dst()))
                    .distinct()
                    .map(cp -> Resources.discrete(resourceId(cp), secondaryT).resource());

            List<Resource> resources = concat(primaryResources, secondaryResources)
                                        .collect(Collectors.toList());
            log.trace("Calling allocate({},{})", intent.key(), resources);
            if (resourceService.allocate(intent.key(), resources).isEmpty()) {
                log.warn("Allocation failed, retrying");
                continue;
            }
            vlans = candidates;
        } while (false);
        log.trace("allocation done.");
        return vlans;
    }

    /**
     * Randomly pick one resource from candidates.
     *
     * @param set of candidates
     * @return chosen one
     * @param <T> label resource type
     */
    <T> T pickOne(Set<T> set) {
        // Note: Set returned by commonLabelResource(..) assures,
        // there is at least one element.

        // FIXME more reasonable selection logic
        return Iterables.get(set, RandomUtils.nextInt(0, set.size()));
    }

    /**
     * Select resource from available Resources.
     *
     * @param primary   Set of resource to pick from
     * @param secondary Set of resource to pick from
     * @return Pair of chosen resource (primary, secondary)
     * @param <T> label resource type
     */
    <T> Pair<T, T> pickEach(Set<T> primary, Set<T> secondary) {
        Set<T> intersection = Sets.intersection(primary, secondary);

        if (!intersection.isEmpty()) {
            // favor common
            T picked = pickOne(intersection);
            return Pair.of(picked, picked);
        }

        T pickedP = pickOne(primary);
        T pickedS = pickOne(secondary);
        return Pair.of(pickedP, pickedS);
    }

    /**
     * Finds label resource, which can be used in common along the path.
     *
     * @param path path
     * @param klass Label class
     * @return Set of common resources
     * @throws IntentCompilationException when there is no resource available
     * @param <T> label resource type
     */
    <T> Set<T> commonLabelResource(Path path, Class<T> klass) {
         Optional<Set<T>> common = path.links().stream()
            .flatMap(link -> Stream.of(link.src(), link.dst()))
            .distinct()
            .map(cp -> getAvailableResourceValues(cp, klass))
            .reduce(Sets::intersection);

         if (!common.isPresent() || common.get().isEmpty()) {
             log.error("No common label available for: {}", path);
             throw new IntentCompilationException("No common label available for: " + path);
         }
         return common.get();
    }

    <T> Set<T> getAvailableResourceValues(ConnectPoint cp, Class<T> klass) {
        return resourceService.getAvailableResourceValues(
                                 resourceId(cp),
                                 klass);
    }

}
