/*
 * 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.List;
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 an edge 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 device D0 is connected to 2 neighbors (D1 and D2 ).
 * The following groups will be created in D0:
 * 1) all ports to D1 + with no label push,
 * 2) all ports to D1 + with label 102 pushed,
 * 3) all ports to D1 + with label 103 pushed,
 * 4) all ports to D2 + with no label push,
 * 5) all ports to D2 + with label 101 pushed,
 * 6) all ports to D2 + with label 103 pushed,
 * 7) all ports to D1 and D2 + with label 103 pushed
 */
public class DefaultEdgeGroupHandler extends DefaultGroupHandler {

    protected DefaultEdgeGroupHandler(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() {
        log.debug("Creating default groups "
                + "for edge device {}", deviceId);
        Set<DeviceId> neighbors = devicePortMap.keySet();
        if (neighbors == null || neighbors.isEmpty()) {
            return;
        }

        // Create all possible Neighbor sets from this router
        Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(neighbors);
        log.trace("createGroupsAtEdgeRouter: The size of neighbor powerset "
                + "for sw {} is {}", deviceId, powerSet.size());
        Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
        for (Set<DeviceId> combo : powerSet) {
            if (combo.isEmpty()) {
                continue;
            }
            List<Integer> groupSegmentIds =
                    getSegmentIdsTobePairedWithNeighborSet(combo);
            for (Integer sId : groupSegmentIds) {
                NeighborSet ns = new NeighborSet(combo, sId);
                log.trace("createGroupsAtEdgeRouter: sw {} "
                        + "combo {} sId {} ns {}",
                        deviceId, combo, sId, ns);
                nsSet.add(ns);
            }
        }
        log.trace("createGroupsAtEdgeRouter: The neighborset "
                + "with label for sw {} is {}",
                deviceId, nsSet);

        createGroupsFromNeighborsets(nsSet);
    }

    @Override
    protected void newNeighbor(Link newNeighborLink) {
        log.debug("New Neighbor: Updating groups "
                + "for edge 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 edge 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<DeviceId>();
        tmp.addAll(updatedNeighbors);
        tmp.remove(impactedNeighbor);
        Set<Set<DeviceId>> tmpPowerSet = getPowerSetOfNeighbors(tmp);

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

        Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
        for (Set<DeviceId> combo : powerSet) {
            if (combo.isEmpty()) {
                continue;
            }
            List<Integer> groupSegmentIds =
                    getSegmentIdsTobePairedWithNeighborSet(combo);
            for (Integer sId : groupSegmentIds) {
                NeighborSet ns = new NeighborSet(combo, sId);
                log.trace("computeImpactedNeighborsetForPortEvent: sw {} "
                        + "combo {} sId {} ns {}",
                        deviceId, combo, sId, ns);
                nsSet.add(ns);
            }
        }
        log.trace("computeImpactedNeighborsetForPortEvent: The neighborset "
                + "with label for sw {} is {}",
                deviceId, nsSet);
        return nsSet;
    }

}
