/*
 * Copyright 2015 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.segmentrouting.grouphandler;

import java.util.HashSet;
import java.util.Set;

import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.link.LinkService;
import org.onosproject.store.service.EventuallyConsistentMap;

/**
 * Default ECMP group handler creation module for a transit device.
 * This component creates a set of ECMP groups for every neighbor
 * that this device is connected to.
 * For example, consider a network of 4 devices: D0 (Segment ID: 100),
 * D1 (Segment ID: 101), D2 (Segment ID: 102) and D3 (Segment ID: 103),
 * where D0 and D3 are edge devices and D1 and D2 are transit devices.
 * Assume transit device D1 is connected to 2 neighbors (D0 and D3 ).
 * The following groups will be created in D1:
 * 1) all ports to D0 + with no label push,
 * 2) all ports to D3 + with no label push,
 */
public class DefaultTransitGroupHandler extends DefaultGroupHandler {

    protected DefaultTransitGroupHandler(DeviceId deviceId,
                                  ApplicationId appId,
                                  DeviceProperties config,
                                  LinkService linkService,
                                  FlowObjectiveService flowObjService,
                                  EventuallyConsistentMap<
                                  NeighborSetNextObjectiveStoreKey,
                                  Integer> nsNextObjStore) {
        super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore);
    }

    @Override
    public void createGroups() {
        Set<DeviceId> neighbors = devicePortMap.keySet();
        if (neighbors == null || neighbors.isEmpty()) {
            return;
        }

        // Create all possible Neighbor sets from this router
        // NOTE: Avoid any pairings of edge routers only
        Set<Set<DeviceId>> sets = getPowerSetOfNeighbors(neighbors);
        sets = filterEdgeRouterOnlyPairings(sets);
        log.debug("createGroupsAtTransitRouter: The size of neighbor powerset "
                + "for sw {} is {}", deviceId, sets.size());
        Set<NeighborSet> nsSet = new HashSet<>();
        for (Set<DeviceId> combo : sets) {
            if (combo.isEmpty()) {
                continue;
            }
            NeighborSet ns = new NeighborSet(combo);
            log.debug("createGroupsAtTransitRouter: sw {} combo {} ns {}",
                      deviceId, combo, ns);
            nsSet.add(ns);
        }
        log.debug("createGroupsAtTransitRouter: The neighborset with label "
                + "for sw {} is {}", deviceId, nsSet);

        createGroupsFromNeighborsets(nsSet);
    }

    @Override
    protected void newNeighbor(Link newNeighborLink) {
        log.debug("New Neighbor: Updating groups for "
                + "transit device {}", deviceId);
        // Recompute neighbor power set
        addNeighborAtPort(newNeighborLink.dst().deviceId(),
                          newNeighborLink.src().port());
        // Compute new neighbor sets due to the addition of new neighbor
        Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
                                             newNeighborLink.dst().deviceId(),
                                             devicePortMap.keySet());
        createGroupsFromNeighborsets(nsSet);
    }

    @Override
    protected void newPortToExistingNeighbor(Link newNeighborLink) {
        /*log.debug("New port to existing neighbor: Updating "
                + "groups for transit device {}", deviceId);
        addNeighborAtPort(newNeighborLink.dst().deviceId(),
                          newNeighborLink.src().port());
        Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
                                              newNeighborLink.dst().deviceId(),
                                              devicePortMap.keySet());
        for (NeighborSet ns : nsSet) {
            // Create the new bucket to be updated
            TrafficTreatment.Builder tBuilder =
                    DefaultTrafficTreatment.builder();
            tBuilder.setOutput(newNeighborLink.src().port())
                    .setEthDst(deviceConfig.getDeviceMac(
                          newNeighborLink.dst().deviceId()))
                    .setEthSrc(nodeMacAddr);
            if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
                tBuilder.pushMpls()
                        .setMpls(MplsLabel.
                                 mplsLabel(ns.getEdgeLabel()));
            }


            Integer nextId = deviceNextObjectiveIds.get(ns);
            if (nextId != null) {
                NextObjective.Builder nextObjBuilder = DefaultNextObjective
                        .builder().withId(nextId)
                        .withType(NextObjective.Type.HASHED).fromApp(appId);

                nextObjBuilder.addTreatment(tBuilder.build());

                NextObjective nextObjective = nextObjBuilder.add();
                flowObjectiveService.next(deviceId, nextObjective);
            }
        }*/
    }

    @Override
    protected Set<NeighborSet> computeImpactedNeighborsetForPortEvent(
                                            DeviceId impactedNeighbor,
                                            Set<DeviceId> updatedNeighbors) {
        Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(updatedNeighbors);

        Set<DeviceId> tmp = new HashSet<>();
        tmp.addAll(updatedNeighbors);
        tmp.remove(impactedNeighbor);
        Set<Set<DeviceId>> tmpPowerSet = getPowerSetOfNeighbors(tmp);

        // Compute the impacted neighbor sets
        powerSet.removeAll(tmpPowerSet);

        powerSet = filterEdgeRouterOnlyPairings(powerSet);
        Set<NeighborSet> nsSet = new HashSet<>();
        for (Set<DeviceId> combo : powerSet) {
            if (combo.isEmpty()) {
                continue;
            }
            NeighborSet ns = new NeighborSet(combo);
            log.debug("createGroupsAtTransitRouter: sw {} combo {} ns {}",
                      deviceId, combo, ns);
            nsSet.add(ns);
        }
        log.debug("computeImpactedNeighborsetForPortEvent: The neighborset with label "
                + "for sw {} is {}", deviceId, nsSet);

        return nsSet;
    }

    private Set<Set<DeviceId>> filterEdgeRouterOnlyPairings(Set<Set<DeviceId>> sets) {
        Set<Set<DeviceId>> fiteredSets = new HashSet<>();
        for (Set<DeviceId> deviceSubSet : sets) {
            if (deviceSubSet.size() > 1) {
                boolean avoidEdgeRouterPairing = true;
                for (DeviceId device : deviceSubSet) {
                    if (!deviceConfig.isEdgeDevice(device)) {
                        avoidEdgeRouterPairing = false;
                        break;
                    }
                }
                if (!avoidEdgeRouterPairing) {
                    fiteredSets.add(deviceSubSet);
                }
            } else {
                fiteredSets.add(deviceSubSet);
            }
        }
        return fiteredSets;
    }
}
