/*
 * 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.SetMultimap;
import javafx.util.Pair;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import org.onosproject.routing.IntentSynchronizationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Synchronizes intents between the in-memory intent store and the
 * IntentService.
 */
public class IntentInstaller {
    private static final Logger log = LoggerFactory.getLogger(
            IntentInstaller.class);

    private static final int PRIORITY_OFFSET = 1000;

    private static final String PREFIX_BROADCAST = "brc";
    private static final String PREFIX_UNICAST = "uni";

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

    /**
     * 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;
    }

    /**
     * Formats the requests for creating and submit intents.
     * Single Points to Multi Point intents are created for all the conigured
     * Connect Points. Multi Point to Single Point intents are created for
     * Connect Points configured that have hosts attached.
     *
     * @param confHostPresentCPoint A map of Connect Points with the eventual
     *                              MAC address of the host attached, by VLAN
     */
    protected void installIntents(SetMultimap<VlanId,
            Pair<ConnectPoint,
                    MacAddress>> confHostPresentCPoint) {
        List<Intent> intents = new ArrayList<>();

        confHostPresentCPoint.asMap().keySet()
                .forEach(vlanId -> {
                    List<Pair<ConnectPoint, MacAddress>> cPoints =
                            confHostPresentCPoint.get(vlanId).stream().collect(Collectors.toList());

                    if (cPoints != null && !cPoints.isEmpty()) {
                        for (int i = 0; i < cPoints.size(); i++) {
                            ConnectPoint src = cPoints.get(i).getKey();
                            Set<ConnectPoint> dsts = new HashSet<>();
                            MacAddress mac = cPoints.get(i).getValue();
                            for (int j = 0; j < cPoints.size(); j++) {
                                ConnectPoint dst = cPoints.get(j).getKey();
                                if (!dst.equals(src)) {
                                    dsts.add(dst);
                                }
                            }
                            Key brcKey = buildKey(PREFIX_BROADCAST, src, vlanId);
                            if (intentService.getIntent(brcKey) == null) {
                                SinglePointToMultiPointIntent brcIntent =
                                        buildBrcIntent(brcKey, src, dsts, vlanId);
                                intents.add(brcIntent);
                            }
                            if (mac != null && countMacInCPoints(cPoints) > 1) {
                                Key uniKey = buildKey(PREFIX_UNICAST, src, vlanId);
                                if (intentService.getIntent(uniKey) == null) {
                                    MultiPointToSinglePointIntent uniIntent =
                                            buildUniIntent(uniKey,
                                                           dsts,
                                                           src,
                                                           vlanId,
                                                           mac);
                                    intents.add(uniIntent);
                                }
                            }
                        }
                    }
                });
        submitIntents(intents);
    }

    /**
     * Requests to install the intents passed as argument to the Intent Service.
     *
     * @param intents intents to be submitted
     */
    private void submitIntents(Collection<Intent> intents) {
        log.debug("Submitting intents to the IntentSynchronizer");

        for (Intent intent : intents) {
            intentSynchronizer.submit(intent);
        }
    }

    /**
     * Builds a Single Point to Multi Point intent.
     *
     * @param src  The source Connect Point
     * @param dsts The destination Connect Points
     * @return Single Point to Multi Point intent generated.
     */
    private SinglePointToMultiPointIntent buildBrcIntent(Key key,
                                                         ConnectPoint src,
                                                         Set<ConnectPoint> dsts,
                                                         VlanId vlanId) {
        log.debug("Building p2mp intent from {}", src);

        SinglePointToMultiPointIntent intent;

        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();

        TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
                .matchEthDst(MacAddress.BROADCAST)
                .matchVlanId(vlanId);

        TrafficSelector selector = builder.build();

        intent = SinglePointToMultiPointIntent.builder()
                .appId(appId)
                .key(key)
                .selector(selector)
                .treatment(treatment)
                .ingressPoint(src)
                .egressPoints(dsts)
                .priority(PRIORITY_OFFSET)
                .build();
        return intent;
    }

    /**
     * Builds a Multi Point to Single Point intent.
     *
     * @param srcs The source Connect Points
     * @param dst  The destination Connect Point
     * @return Multi Point to Single Point intent generated.
     */
    private MultiPointToSinglePointIntent buildUniIntent(Key key,
                                                         Set<ConnectPoint> srcs,
                                                         ConnectPoint dst,
                                                         VlanId vlanId,
                                                         MacAddress mac) {
        log.debug("Building mp2p intent to {}", dst);

        MultiPointToSinglePointIntent intent;

        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();

        TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
                .matchEthDst(mac)
                .matchVlanId(vlanId);

        TrafficSelector selector = builder.build();

        intent = MultiPointToSinglePointIntent.builder()
                .appId(appId)
                .key(key)
                .selector(selector)
                .treatment(treatment)
                .ingressPoints(srcs)
                .egressPoint(dst)
                .priority(PRIORITY_OFFSET)
                .build();
        return intent;
    }

    /**
     * Builds an intent Key for either for a Single Point to Multi Point or
     * Multi Point to Single Point intent, based on a prefix that defines
     * the type of intent, the single connection point representing the source
     * or the destination and the vlan id representing the network.
     *
     * @param cPoint the source or destination connect point
     * @param vlanId the network vlan id
     * @param prefix prefix string
     * @return
     */
    private Key buildKey(String prefix, ConnectPoint cPoint, VlanId vlanId) {
        String keyString = new StringBuilder()
                .append(prefix)
                .append("-")
                .append(cPoint.deviceId())
                .append("-")
                .append(cPoint.port())
                .append("-")
                .append(vlanId)
                .toString();

        return Key.of(keyString, appId);
    }

    /**
     * Counts the number of mac addresses associated to a specific list of
     * ConnectPoint.
     *
     * @param cPoints List of ConnectPoints, eventually binded to the MAC of the
     *                host attached
     * @return number of mac addresses found.
     */
    private int countMacInCPoints(List<Pair<ConnectPoint, MacAddress>> cPoints) {
        int macFound = 0;
        for (Pair<ConnectPoint, MacAddress> p : cPoints) {
            if (p.getValue() != null) {
                macFound++;
            }
        }
        return macFound;
    }

}
