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

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.NetworkConfigEvent;
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.flow.criteria.Criteria;
import org.onosproject.net.flowobjective.DefaultFilteringObjective;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.DefaultNextObjective;
import org.onosproject.net.flowobjective.DefaultObjectiveContext;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.segmentrouting.config.XConnectConfig;
import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.Serializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * Handles cross connect related events.
 *
 * @deprecated in ONOS 1.12. Replaced by {@link org.onosproject.segmentrouting.xconnect.impl.XconnectManager}
 */
@Deprecated
public class XConnectHandler {
    private static final Logger log = LoggerFactory.getLogger(XConnectHandler.class);
    private static final String CONFIG_NOT_FOUND = "XConnect config not found";
    private static final String NOT_MASTER = "Not master controller";
    private final SegmentRoutingManager srManager;
    private final ConsistentMap<XConnectStoreKey, NextObjective> xConnectNextObjStore;

    XConnectHandler(SegmentRoutingManager srManager) {
        this.srManager = srManager;
        KryoNamespace.Builder xConnectKryo = new KryoNamespace.Builder()
                .register(KryoNamespaces.API)
                .register(XConnectStoreKey.class)
                .register(NextObjContext.class);
        xConnectNextObjStore = srManager.storageService
                .<XConnectStoreKey, NextObjective>consistentMapBuilder()
                .withName("onos-xconnect-nextobj-store")
                .withSerializer(Serializer.using(xConnectKryo.build()))
                .build();
    }

    /**
     * Read initial XConnect for given device.
     *
     * @param deviceId ID of the device to be initialized
     */
    public void init(DeviceId deviceId) {
        // Try to read XConnect config
        XConnectConfig config =
                srManager.cfgService.getConfig(srManager.appId, XConnectConfig.class);
        if (config == null) {
            log.info("Skip XConnect initialization: {}", CONFIG_NOT_FOUND);
            return;
        }

        config.getXconnects(deviceId).forEach(key -> populateXConnect(key, config.getPorts(key)));
    }

    /**
     * Processes Segment Routing App Config added event.
     *
     * @param event network config added event
     */
    void processXConnectConfigAdded(NetworkConfigEvent event) {
        log.info("Processing XConnect CONFIG_ADDED");
        XConnectConfig config = (XConnectConfig) event.config().get();
        config.getXconnects().forEach(key -> populateXConnect(key, config.getPorts(key)));
    }

    /**
     * Processes Segment Routing App Config updated event.
     *
     * @param event network config updated event
     */
    void processXConnectConfigUpdated(NetworkConfigEvent event) {
        log.info("Processing XConnect CONFIG_UPDATED");
        XConnectConfig prevConfig = (XConnectConfig) event.prevConfig().get();
        XConnectConfig config = (XConnectConfig) event.config().get();
        Set<XConnectStoreKey> prevKeys = prevConfig.getXconnects();
        Set<XConnectStoreKey> keys = config.getXconnects();

        Set<XConnectStoreKey> pendingRemove = prevKeys.stream()
                .filter(key -> !keys.contains(key)).collect(Collectors.toSet());
        Set<XConnectStoreKey> pendingAdd = keys.stream()
                .filter(key -> !prevKeys.contains(key)).collect(Collectors.toSet());
        Set<XConnectStoreKey> pendingUpdate = keys.stream()
                .filter(key -> prevKeys.contains(key) &&
                        !config.getPorts(key).equals(prevConfig.getPorts(key)))
                .collect(Collectors.toSet());

        pendingRemove.forEach(key -> revokeXConnect(key, prevConfig.getPorts(key)));
        pendingAdd.forEach(key -> populateXConnect(key, config.getPorts(key)));
        pendingUpdate.forEach(key ->
                updateXConnect(key, prevConfig.getPorts(key), config.getPorts(key)));
    }

    /**
     * Processes Segment Routing App Config removed event.
     *
     * @param event network config removed event
     */
    void processXConnectConfigRemoved(NetworkConfigEvent event) {
        log.info("Processing XConnect CONFIG_REMOVED");
        XConnectConfig prevConfig = (XConnectConfig) event.prevConfig().get();
        prevConfig.getXconnects().forEach(key -> {
            revokeXConnect(key, prevConfig.getPorts(key));
        });
    }

    /**
     * Checks if there is any XConnect configured on given connect point.
     *
     * @param cp connect point
     * @return true if there is XConnect configured on given connect point.
     */
    public boolean hasXConnect(ConnectPoint cp) {
        // Try to read XConnect config
        XConnectConfig config =
                srManager.cfgService.getConfig(srManager.appId, XConnectConfig.class);
        if (config == null) {
            log.warn("Failed to read XConnect config: {}", CONFIG_NOT_FOUND);
            return false;
        }
        return config.getXconnects(cp.deviceId()).stream()
                .anyMatch(key -> config.getPorts(key).contains(cp.port()));
    }

    /**
     * Populates XConnect groups and flows for given key.
     *
     * @param key XConnect key
     * @param ports a set of ports to be cross-connected
     */
    private void populateXConnect(XConnectStoreKey key, Set<PortNumber> ports) {
        if (!srManager.mastershipService.isLocalMaster(key.deviceId())) {
            log.info("Abort populating XConnect {}: {}", key, NOT_MASTER);
            return;
        }

        ports = addPairPort(key.deviceId(), ports);
        populateFilter(key, ports);
        populateFwd(key, populateNext(key, ports));
        populateAcl(key);
    }

    /**
     * Populates filtering objectives for given XConnect.
     *
     * @param key XConnect store key
     * @param ports XConnect ports
     */
    private void populateFilter(XConnectStoreKey key, Set<PortNumber> ports) {
        ports.forEach(port -> {
            FilteringObjective.Builder filtObjBuilder = filterObjBuilder(key, port);
            ObjectiveContext context = new DefaultObjectiveContext(
                    (objective) -> log.debug("XConnect FilterObj for {} on port {} populated",
                            key, port),
                    (objective, error) ->
                            log.warn("Failed to populate XConnect FilterObj for {} on port {}: {}",
                                    key, port, error));
            srManager.flowObjectiveService.filter(key.deviceId(), filtObjBuilder.add(context));
        });
    }

    /**
     * Populates next objectives for given XConnect.
     *
     * @param key XConnect store key
     * @param ports XConnect ports
     */
    private NextObjective populateNext(XConnectStoreKey key, Set<PortNumber> ports) {
        NextObjective nextObj;
        if (xConnectNextObjStore.containsKey(key)) {
            nextObj = xConnectNextObjStore.get(key).value();
            log.debug("NextObj for {} found, id={}", key, nextObj.id());
        } else {
            NextObjective.Builder nextObjBuilder = nextObjBuilder(key, ports);
            ObjectiveContext nextContext = new NextObjContext(Objective.Operation.ADD, key);
            nextObj = nextObjBuilder.add(nextContext);
            srManager.flowObjectiveService.next(key.deviceId(), nextObj);
            xConnectNextObjStore.put(key, nextObj);
            log.debug("NextObj for {} not found. Creating new NextObj with id={}", key, nextObj.id());
        }
        return nextObj;
    }

    /**
     * Populates bridging forwarding objectives for given XConnect.
     *
     * @param key XConnect store key
     * @param nextObj next objective
     */
    private void populateFwd(XConnectStoreKey key, NextObjective nextObj) {
        ForwardingObjective.Builder fwdObjBuilder = fwdObjBuilder(key, nextObj.id());
        ObjectiveContext fwdContext = new DefaultObjectiveContext(
                (objective) -> log.debug("XConnect FwdObj for {} populated", key),
                (objective, error) ->
                        log.warn("Failed to populate XConnect FwdObj for {}: {}", key, error));
        srManager.flowObjectiveService.forward(key.deviceId(), fwdObjBuilder.add(fwdContext));
    }

    /**
     * Populates ACL forwarding objectives for given XConnect.
     *
     * @param key XConnect store key
     */
    private void populateAcl(XConnectStoreKey key) {
        ForwardingObjective.Builder aclObjBuilder = aclObjBuilder(key.vlanId());
        ObjectiveContext aclContext = new DefaultObjectiveContext(
                (objective) -> log.debug("XConnect AclObj for {} populated", key),
                (objective, error) ->
                        log.warn("Failed to populate XConnect AclObj for {}: {}", key, error));
        srManager.flowObjectiveService.forward(key.deviceId(), aclObjBuilder.add(aclContext));
    }

    /**
     * Revokes XConnect groups and flows for given key.
     *
     * @param key XConnect key
     * @param ports XConnect ports
     */
    private void revokeXConnect(XConnectStoreKey key, Set<PortNumber> ports) {
        if (!srManager.mastershipService.isLocalMaster(key.deviceId())) {
            log.info("Abort populating XConnect {}: {}", key, NOT_MASTER);
            return;
        }

        ports = addPairPort(key.deviceId(), ports);
        revokeFilter(key, ports);
        if (xConnectNextObjStore.containsKey(key)) {
            NextObjective nextObj = xConnectNextObjStore.get(key).value();
            revokeFwd(key, nextObj, null);
            revokeNext(key, nextObj, null);
        } else {
            log.warn("NextObj for {} does not exist in the store.", key);
        }
        revokeAcl(key);
    }

    /**
     * Revokes filtering objectives for given XConnect.
     *
     * @param key XConnect store key
     * @param ports XConnect ports
     */
    private void revokeFilter(XConnectStoreKey key, Set<PortNumber> ports) {
        ports.forEach(port -> {
            FilteringObjective.Builder filtObjBuilder = filterObjBuilder(key, port);
            ObjectiveContext context = new DefaultObjectiveContext(
                    (objective) -> log.debug("XConnect FilterObj for {} on port {} revoked",
                            key, port),
                    (objective, error) ->
                            log.warn("Failed to revoke XConnect FilterObj for {} on port {}: {}",
                                    key, port, error));
            srManager.flowObjectiveService.filter(key.deviceId(), filtObjBuilder.remove(context));
        });
    }

    /**
     * Revokes next objectives for given XConnect.
     *
     * @param key XConnect store key
     * @param nextObj next objective
     * @param nextFuture completable future for this next objective operation
     */
    private void revokeNext(XConnectStoreKey key, NextObjective nextObj,
            CompletableFuture<ObjectiveError> nextFuture) {
        ObjectiveContext context = new ObjectiveContext() {
            @Override
            public void onSuccess(Objective objective) {
                log.debug("Previous NextObj for {} removed", key);
                if (nextFuture != null) {
                    nextFuture.complete(null);
                }
            }

            @Override
            public void onError(Objective objective, ObjectiveError error) {
                log.warn("Failed to remove previous NextObj for {}: {}", key, error);
                if (nextFuture != null) {
                    nextFuture.complete(error);
                }
            }
        };
        srManager.flowObjectiveService.next(key.deviceId(),
                (NextObjective) nextObj.copy().remove(context));
        xConnectNextObjStore.remove(key);
    }

    /**
     * Revokes bridging forwarding objectives for given XConnect.
     *
     * @param key XConnect store key
     * @param nextObj next objective
     * @param fwdFuture completable future for this forwarding objective operation
     */
    private void revokeFwd(XConnectStoreKey key, NextObjective nextObj,
            CompletableFuture<ObjectiveError> fwdFuture) {
        ForwardingObjective.Builder fwdObjBuilder = fwdObjBuilder(key, nextObj.id());
        ObjectiveContext context = new ObjectiveContext() {
            @Override
            public void onSuccess(Objective objective) {
                log.debug("Previous FwdObj for {} removed", key);
                if (fwdFuture != null) {
                    fwdFuture.complete(null);
                }
            }

            @Override
            public void onError(Objective objective, ObjectiveError error) {
                log.warn("Failed to remove previous FwdObj for {}: {}", key, error);
                if (fwdFuture != null) {
                    fwdFuture.complete(error);
                }
            }
        };
        srManager.flowObjectiveService
                .forward(key.deviceId(), fwdObjBuilder.remove(context));
    }

    /**
     * Revokes ACL forwarding objectives for given XConnect.
     *
     * @param key XConnect store key
     */
    private void revokeAcl(XConnectStoreKey key) {
        ForwardingObjective.Builder aclObjBuilder = aclObjBuilder(key.vlanId());
        ObjectiveContext aclContext = new DefaultObjectiveContext(
                (objective) -> log.debug("XConnect AclObj for {} populated", key),
                (objective, error) ->
                        log.warn("Failed to populate XConnect AclObj for {}: {}", key, error));
        srManager.flowObjectiveService
                .forward(key.deviceId(), aclObjBuilder.remove(aclContext));
    }

    /**
     * Updates XConnect groups and flows for given key.
     *
     * @param key XConnect key
     * @param prevPorts previous XConnect ports
     * @param ports new XConnect ports
     */
    private void updateXConnect(XConnectStoreKey key, Set<PortNumber> prevPorts,
            Set<PortNumber> ports) {
        // NOTE: ACL flow doesn't include port information. No need to update it.
        //       Pair port is built-in and thus not going to change. No need to update it.

        // remove old filter
        prevPorts.stream().filter(port -> !ports.contains(port)).forEach(port ->
            revokeFilter(key, ImmutableSet.of(port)));
        // install new filter
        ports.stream().filter(port -> !prevPorts.contains(port)).forEach(port ->
            populateFilter(key, ImmutableSet.of(port)));

        CompletableFuture<ObjectiveError> fwdFuture = new CompletableFuture<>();
        CompletableFuture<ObjectiveError> nextFuture = new CompletableFuture<>();

        if (xConnectNextObjStore.containsKey(key)) {
            NextObjective nextObj = xConnectNextObjStore.get(key).value();
            revokeFwd(key, nextObj, fwdFuture);

            fwdFuture.thenAcceptAsync(fwdStatus -> {
                if (fwdStatus == null) {
                    log.debug("Fwd removed. Now remove group {}", key);
                    revokeNext(key, nextObj, nextFuture);
                }
            });

            nextFuture.thenAcceptAsync(nextStatus -> {
                if (nextStatus == null) {
                    log.debug("Installing new group and flow for {}", key);
                    populateFwd(key, populateNext(key, ports));
                }
            });
        } else {
            log.warn("NextObj for {} does not exist in the store.", key);
        }
    }

    /**
     * Remove all groups on given device.
     *
     * @param deviceId device ID
     */
    void removeDevice(DeviceId deviceId) {
        xConnectNextObjStore.entrySet().stream()
                .filter(entry -> entry.getKey().deviceId().equals(deviceId))
                .forEach(entry -> xConnectNextObjStore.remove(entry.getKey()));
        log.debug("{} is removed from xConnectNextObjStore", deviceId);
    }

    /**
     * Creates a next objective builder for XConnect.
     *
     * @param key XConnect key
     * @param ports set of XConnect ports
     * @return next objective builder
     */
    private NextObjective.Builder nextObjBuilder(XConnectStoreKey key, Set<PortNumber> ports) {
        int nextId = srManager.flowObjectiveService.allocateNextId();
        TrafficSelector metadata =
                DefaultTrafficSelector.builder().matchVlanId(key.vlanId()).build();
        NextObjective.Builder nextObjBuilder = DefaultNextObjective
                .builder().withId(nextId)
                .withType(NextObjective.Type.BROADCAST).fromApp(srManager.appId)
                .withMeta(metadata);
        ports.forEach(port -> {
            TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
            tBuilder.setOutput(port);
            nextObjBuilder.addTreatment(tBuilder.build());
        });
        return nextObjBuilder;
    }

    /**
     * Creates a bridging forwarding objective builder for XConnect.
     *
     * @param key XConnect key
     * @param nextId next ID of the broadcast group for this XConnect key
     * @return forwarding objective builder
     */
    private ForwardingObjective.Builder fwdObjBuilder(XConnectStoreKey key, int nextId) {
        /*
         * Driver should treat objectives with MacAddress.NONE and !VlanId.NONE
         * as the VLAN cross-connect broadcast rules
         */
        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
        sbuilder.matchVlanId(key.vlanId());
        sbuilder.matchEthDst(MacAddress.NONE);

        ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
        fob.withFlag(ForwardingObjective.Flag.SPECIFIC)
                .withSelector(sbuilder.build())
                .nextStep(nextId)
                .withPriority(SegmentRoutingService.XCONNECT_PRIORITY)
                .fromApp(srManager.appId)
                .makePermanent();
        return fob;
    }

    /**
     * Creates an ACL forwarding objective builder for XConnect.
     *
     * @param vlanId cross connect VLAN id
     * @return forwarding objective builder
     */
    private ForwardingObjective.Builder aclObjBuilder(VlanId vlanId) {
        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
        sbuilder.matchVlanId(vlanId);

        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();

        ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
        fob.withFlag(ForwardingObjective.Flag.VERSATILE)
                .withSelector(sbuilder.build())
                .withTreatment(tbuilder.build())
                .withPriority(SegmentRoutingService.XCONNECT_ACL_PRIORITY)
                .fromApp(srManager.appId)
                .makePermanent();
        return fob;
    }

    /**
     * Creates a filtering objective builder for XConnect.
     *
     * @param key XConnect key
     * @param port XConnect ports
     * @return next objective builder
     */
    private FilteringObjective.Builder filterObjBuilder(XConnectStoreKey key, PortNumber port) {
        FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
        fob.withKey(Criteria.matchInPort(port))
                .addCondition(Criteria.matchVlanId(key.vlanId()))
                .addCondition(Criteria.matchEthDst(MacAddress.NONE))
                .withPriority(SegmentRoutingService.XCONNECT_PRIORITY);
        return fob.permit().fromApp(srManager.appId);
    }

    /**
     * Add pair port to the given set of port.
     *
     * @param deviceId device Id
     * @param ports ports specified in the xconnect config
     * @return port specified in the xconnect config plus the pair port (if configured)
     */
    private Set<PortNumber> addPairPort(DeviceId deviceId, Set<PortNumber> ports) {
        Set<PortNumber> newPorts = Sets.newHashSet(ports);
        srManager.getPairLocalPort(deviceId).ifPresent(newPorts::add);
        return newPorts;
    }

    // TODO: Lambda closure in DefaultObjectiveContext cannot be serialized properly
    //       with Kryo 3.0.3. It will be fixed in 3.0.4. By then we can use
    //       DefaultObjectiveContext again.
    private final class NextObjContext implements ObjectiveContext {
        Objective.Operation op;
        XConnectStoreKey key;

        private NextObjContext(Objective.Operation op, XConnectStoreKey key) {
            this.op = op;
            this.key = key;
        }

        @Override
        public void onSuccess(Objective objective) {
            log.debug("XConnect NextObj for {} {}ED", key, op);
        }

        @Override
        public void onError(Objective objective, ObjectiveError error) {
            log.warn("Failed to {} XConnect NextObj for {}: {}", op, key, error);
        }
    }
}
