/*
 * 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.vpls;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.EncapsulationType;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.intent.ConnectivityIntent;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import org.onosproject.net.intent.constraint.EncapsulationConstraint;
import org.onosproject.net.intent.constraint.PartialFailureConstraint;
import org.onosproject.intentsync.IntentSynchronizationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import static org.onosproject.net.EncapsulationType.*;

/**
 * Synchronizes intents between the in-memory intent store and the
 * IntentService.
 */
public class IntentInstaller {
    private static final String SUBMIT =
            "Submitting intents to the Intent Synchronizer";
    private static final String WITHDRAW =
            "Withdrawing intents to the Intent Synchronizer";
    private static final String SP2MP =
            "Building sp2mp intent from {}";
    private static final String MP2SP =
            "Building mp2sp intent to {}";

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

    private static final int PRIORITY_OFFSET = 1000;

    private static final Set<IntentState> WITHDRAWN_INTENT_STATES =
            ImmutableSet.of(IntentState.WITHDRAWN,
                            IntentState.WITHDRAW_REQ,
                            IntentState.WITHDRAWING);

    static final String PREFIX_BROADCAST = "brc";
    static final String PREFIX_UNICAST = "uni";
    static final String SEPARATOR = "-";

    private final ApplicationId appId;
    private final IntentSynchronizationService intentSynchronizer;
    private final IntentService intentService;

    public static final ImmutableList<Constraint> PARTIAL_FAILURE_CONSTRAINT =
            ImmutableList.of(new PartialFailureConstraint());

    /**
     * Class constructor.
     *
     * @param appId              the Application ID
     * @param intentService      the intent service
     * @param intentSynchronizer the intent synchronizer service
     */
    public IntentInstaller(ApplicationId appId, IntentService intentService,
                           IntentSynchronizationService intentSynchronizer) {
        this.appId = appId;
        this.intentService = intentService;
        this.intentSynchronizer = intentSynchronizer;
    }

    /**
     * Requests to install the intents passed as argument to the Intent Service.
     *
     * @param intents intents to be submitted
     */
    protected void submitIntents(Collection<Intent> intents) {
        log.debug(SUBMIT);
        intents.forEach(intentSynchronizer::submit);
    }

    /**
     * Requests to withdraw the intents passed as argument to the Intent Service.
     *
     * @param intents intents to be withdraw
     */
    protected void withdrawIntents(Collection<Intent> intents) {
        log.debug(WITHDRAW);
        intents.forEach(intentSynchronizer::withdraw);
    }

    /**
     * Returns list of intents belongs to a VPLS.
     *
     * @param name the name of the VPLS
     * @return the list of intents belonging to a VPLS
     */
    protected List<Intent> getIntentsFromVpls(String name) {
        List<Intent> intents = Lists.newArrayList();

        intentService.getIntents().forEach(intent -> {
            if (intent.key().toString().startsWith(name)) {
                intents.add(intent);
            }
        });

        return intents;
    }

    /**
     * Builds a broadcast intent.
     *
     * @param key key to identify the intent
     * @param src the source connect point
     * @param dsts the destination connect points
     * @param encap the encapsulation type
     * @return the generated single-point to multi-point intent
     */
    protected SinglePointToMultiPointIntent buildBrcIntent(Key key,
                                                           FilteredConnectPoint src,
                                                           Set<FilteredConnectPoint> dsts,
                                                           EncapsulationType encap) {
        log.debug("Building broadcast intent {} for source {}", SP2MP, src);

        SinglePointToMultiPointIntent.Builder intentBuilder;

        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchEthDst(MacAddress.BROADCAST)
                .build();

        intentBuilder = SinglePointToMultiPointIntent.builder()
                .appId(appId)
                .key(key)
                .selector(selector)
                .filteredIngressPoint(src)
                .filteredEgressPoints(dsts)
                .constraints(PARTIAL_FAILURE_CONSTRAINT)
                .priority(PRIORITY_OFFSET);

        setEncap(intentBuilder, PARTIAL_FAILURE_CONSTRAINT, encap);

        return intentBuilder.build();
    }

    /**
     * Builds a unicast intent.
     *
     * @param key key to identify the intent
     * @param srcs the source Connect Points
     * @param dst the destination Connect Point
     * @param host destination Host
     * @param encap the encapsulation type
     * @return the generated multi-point to single-point intent
     */
    protected MultiPointToSinglePointIntent buildUniIntent(Key key,
                                                           Set<FilteredConnectPoint> srcs,
                                                           FilteredConnectPoint dst,
                                                           Host host,
                                                           EncapsulationType encap) {
        log.debug("Building unicast intent {} for destination {}", MP2SP, dst);

        MultiPointToSinglePointIntent.Builder intentBuilder;

        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchEthDst(host.mac())
                .build();

        intentBuilder = MultiPointToSinglePointIntent.builder()
                .appId(appId)
                .key(key)
                .selector(selector)
                .filteredIngressPoints(srcs)
                .filteredEgressPoint(dst)
                .constraints(PARTIAL_FAILURE_CONSTRAINT)
                .priority(PRIORITY_OFFSET);

        setEncap(intentBuilder, PARTIAL_FAILURE_CONSTRAINT, encap);

        return intentBuilder.build();
    }

    /**
     * Builds an intent key either for single-point to multi-point or
     * multi-point to single-point intents, based on a prefix that defines
     * the type of intent, the single connect point representing the single
     * source or destination for that intent, the name of the VPLS the intent
     * belongs to, and the destination host MAC address the intent reaches.
     *
     * @param prefix the key prefix
     * @param cPoint the connect point identifying the source/destination
     * @param vplsName the name of the VPLS
     * @param hostMac the source/destination MAC address
     * @return the key to identify the intent
     */
    protected Key buildKey(String prefix,
                           ConnectPoint cPoint,
                           String vplsName,
                           MacAddress hostMac) {
        String keyString = vplsName +
                SEPARATOR +
                prefix +
                SEPARATOR +
                cPoint.deviceId() +
                SEPARATOR +
                cPoint.port() +
                SEPARATOR +
                hostMac;

        return Key.of(keyString, appId);
    }

    /**
     * Returns true if the specified intent exists; false otherwise.
     *
     * @param intentKey the intent key
     * @return true if the intent exists; false otherwise
     */
    protected boolean intentExists(Key intentKey) {
        if (intentService.getIntent(intentKey) == null) {
            return false;
        }

        // Intent does not exist if intent withdrawn
        IntentState currentIntentState = intentService.getIntentState(intentKey);
        return !WITHDRAWN_INTENT_STATES.contains(currentIntentState);

    }

    /**
     * Sets one or more encapsulation constraints on the intent builder given.
     *
     * @param builder the intent builder
     * @param constraints the existing intent constraints
     * @param encap the encapsulation type to be set
     */
    public static void setEncap(ConnectivityIntent.Builder builder,
                                List<Constraint> constraints,
                                EncapsulationType encap) {
        // Constraints might be an immutable list, so a new modifiable list
        // is created
        List<Constraint> newConstraints = new ArrayList<>(constraints);

        // Remove any encapsulation constraint if already in the list
        constraints.stream()
                .filter(c -> c instanceof EncapsulationConstraint)
                .forEach(newConstraints::remove);

        // if the new encapsulation is different from NONE, a new encapsulation
        // constraint should be added to the list
        if (!encap.equals(NONE)) {
            newConstraints.add(new EncapsulationConstraint(encap));
        }

        // Submit new constraint list as immutable list
        builder.constraints(ImmutableList.copyOf(newConstraints));
    }
}
