/*
 * Copyright 2017-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.pipelines.fabric.pipeliner;

import com.google.common.collect.Lists;
import org.onlab.packet.VlanId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
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.Criterion;
import org.onosproject.net.flow.criteria.PiCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onosproject.net.flowobjective.DefaultNextTreatment;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.flowobjective.NextTreatment;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.group.DefaultGroupBucket;
import org.onosproject.net.group.DefaultGroupDescription;
import org.onosproject.net.group.DefaultGroupKey;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupKey;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.net.pi.runtime.PiActionProfileGroupId;
import org.onosproject.net.pi.runtime.PiGroupKey;
import org.onosproject.pipelines.fabric.FabricCapabilities;
import org.onosproject.pipelines.fabric.FabricConstants;
import org.onosproject.pipelines.fabric.FabricUtils;

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static java.lang.String.format;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_ID;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_POP;
import static org.onosproject.pipelines.fabric.FabricUtils.criterion;
import static org.onosproject.pipelines.fabric.FabricUtils.l2Instruction;
import static org.onosproject.pipelines.fabric.FabricUtils.outputPort;

/**
 * ObjectiveTranslator implementation for NextObjective.
 */
class NextObjectiveTranslator
        extends AbstractObjectiveTranslator<NextObjective> {

    private static final String XCONNECT = "xconnect";

    NextObjectiveTranslator(DeviceId deviceId, FabricCapabilities capabilities) {
        super(deviceId, capabilities);
    }

    @Override
    public ObjectiveTranslation doTranslate(NextObjective obj)
            throws FabricPipelinerException {

        final ObjectiveTranslation.Builder resultBuilder =
                ObjectiveTranslation.builder();

        switch (obj.type()) {
            case SIMPLE:
                simpleNext(obj, resultBuilder, false);
                break;
            case HASHED:
                hashedNext(obj, resultBuilder);
                break;
            case BROADCAST:
                if (isXconnect(obj)) {
                    xconnectNext(obj, resultBuilder);
                } else {
                    multicastNext(obj, resultBuilder);
                }
                break;
            default:
                log.warn("Unsupported NextObjective type '{}'", obj);
                return ObjectiveTranslation.ofError(ObjectiveError.UNSUPPORTED);
        }

        if (!isGroupModifyOp(obj)) {
            // Generate next VLAN rules.
            nextVlan(obj, resultBuilder);
        }

        return resultBuilder.build();
    }

    private void nextVlan(NextObjective obj,
                          ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        // Set the egress VLAN for this next ID. Expect either a VLAN_ID
        // criterion in meta, or a VLAN_ID instruction in the treatment (if
        // SIMPLE, e.g. for a routing rule).

        final VlanIdCriterion vlanIdCriterion = obj.meta() == null ? null
                : (VlanIdCriterion) criterion(obj.meta().criteria(), Criterion.Type.VLAN_VID);
        final ModVlanIdInstruction vlanIdInstruction;
        if (obj.type() == NextObjective.Type.SIMPLE) {
            final TrafficTreatment treatment = getFirstDefaultNextTreatmentIfAny(
                    obj.nextTreatments());
            vlanIdInstruction = treatment == null ? null
                    : (ModVlanIdInstruction) l2Instruction(treatment, VLAN_ID);
        } else {
            vlanIdInstruction = null;
        }

        if (vlanIdCriterion == null && vlanIdInstruction == null) {
            // Do nothing.
            return;
        }

        if (vlanIdCriterion != null && vlanIdInstruction != null) {
            if (!vlanIdCriterion.vlanId().equals(vlanIdInstruction.vlanId())) {
                throw new FabricPipelinerException(
                        "Found both meta VLAN_ID criterion and VLAN_ID " +
                                "treatment, but they have different ID " +
                                "values. Cannot process next_vlan rule.");
            }
        }

        final VlanId vlanId = vlanIdCriterion != null
                ? vlanIdCriterion.vlanId() : vlanIdInstruction.vlanId();

        final TrafficSelector selector = nextIdSelector(obj.id());
        final TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .setVlanId(vlanId)
                .build();

        resultBuilder.addFlowRule(flowRule(
                obj, FabricConstants.FABRIC_INGRESS_NEXT_NEXT_VLAN,
                selector, treatment));
    }

    private void simpleNext(NextObjective obj,
                            ObjectiveTranslation.Builder resultBuilder,
                            boolean forceSimple)
            throws FabricPipelinerException {

        if (capabilities.hasHashedTable()) {
            // Use hashed table when possible.
            hashedNext(obj, resultBuilder);
            return;
        }

        if (obj.nextTreatments().isEmpty()) {
            // Do nothing.
            return;
        } else if (!forceSimple && obj.nextTreatments().size() != 1) {
            throw new FabricPipelinerException(format(
                    "SIMPLE NextObjective should contain only 1 treatment, found %d",
                    obj.nextTreatments().size()), ObjectiveError.BADPARAMS);
        }

        final TrafficSelector selector = nextIdSelector(obj.id());

        final List<DefaultNextTreatment> treatments = defaultNextTreatments(
                obj.nextTreatments(), true);

        if (forceSimple && treatments.size() > 1) {
            log.warn("Forcing SIMPLE behavior for NextObjective with {} treatments []",
                     treatments.size(), obj);
        }

        // If not forcing, we are essentially extracting the only available treatment.
        final TrafficTreatment treatment = defaultNextTreatments(
                obj.nextTreatments(), true).get(0).treatment();

        resultBuilder.addFlowRule(flowRule(
                obj, FabricConstants.FABRIC_INGRESS_NEXT_SIMPLE,
                selector, treatment));

        handleEgress(obj, treatment, resultBuilder, false);
    }

    private void hashedNext(NextObjective obj,
                            ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        if (!capabilities.hasHashedTable()) {
            simpleNext(obj, resultBuilder, true);
            return;
        }

        // Updated result builder with hashed group.
        final int groupId = selectGroup(obj, resultBuilder);

        if (isGroupModifyOp(obj)) {
            // No changes to flow rules.
            return;
        }

        final TrafficSelector selector = nextIdSelector(obj.id());
        final TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .piTableAction(PiActionProfileGroupId.of(groupId))
                .build();

        resultBuilder.addFlowRule(flowRule(
                obj, FabricConstants.FABRIC_INGRESS_NEXT_HASHED,
                selector, treatment));
    }

    private void handleEgress(NextObjective obj, TrafficTreatment treatment,
                              ObjectiveTranslation.Builder resultBuilder,
                              boolean strict)
            throws FabricPipelinerException {
        final PortNumber outPort = outputPort(treatment);
        final Instruction popVlanInst = l2Instruction(treatment, VLAN_POP);
        if (popVlanInst != null && outPort != null) {
            if (strict && treatment.allInstructions().size() > 2) {
                throw new FabricPipelinerException(
                        "Treatment contains instructions other " +
                                "than OUTPUT and VLAN_POP, cannot generate " +
                                "egress rules");
            }
            egressVlanPop(outPort, obj, resultBuilder);
        }
    }

    private void egressVlanPop(PortNumber outPort, NextObjective obj,
                               ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        if (obj.meta() == null) {
            throw new FabricPipelinerException(
                    "Cannot process egress pop VLAN rule, NextObjective has null meta",
                    ObjectiveError.BADPARAMS);
        }

        final VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) criterion(
                obj.meta(), Criterion.Type.VLAN_VID);
        if (vlanIdCriterion == null) {
            throw new FabricPipelinerException(
                    "Cannot process egress pop VLAN rule, missing VLAN_VID criterion " +
                            "in NextObjective meta",
                    ObjectiveError.BADPARAMS);
        }

        final PiCriterion egressVlanTableMatch = PiCriterion.builder()
                .matchExact(FabricConstants.HDR_EG_PORT, outPort.toLong())
                .build();
        final TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchPi(egressVlanTableMatch)
                .matchVlanId(vlanIdCriterion.vlanId())
                .build();
        final TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .popVlan()
                .build();

        resultBuilder.addFlowRule(flowRule(
                obj, FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN,
                selector, treatment));
    }

    private TrafficSelector nextIdSelector(int nextId) {
        return nextIdSelectorBuilder(nextId).build();
    }

    private TrafficSelector.Builder nextIdSelectorBuilder(int nextId) {
        final PiCriterion nextIdCriterion = PiCriterion.builder()
                .matchExact(FabricConstants.HDR_NEXT_ID, nextId)
                .build();
        return DefaultTrafficSelector.builder()
                .matchPi(nextIdCriterion);
    }

    private void xconnectNext(NextObjective obj, ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        final Collection<DefaultNextTreatment> defaultNextTreatments =
                defaultNextTreatments(obj.nextTreatments(), true);

        final List<PortNumber> outPorts = defaultNextTreatments.stream()
                .map(DefaultNextTreatment::treatment)
                .map(FabricUtils::outputPort)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (outPorts.size() != 2) {
            throw new FabricPipelinerException(format(
                    "Handling XCONNECT with %d treatments (ports), but expected is 2",
                    defaultNextTreatments.size()), ObjectiveError.UNSUPPORTED);
        }

        final PortNumber port1 = outPorts.get(0);
        final PortNumber port2 = outPorts.get(1);
        final TrafficSelector selector1 = nextIdSelectorBuilder(obj.id())
                .matchInPort(port1)
                .build();
        final TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
                .setOutput(port2)
                .build();
        final TrafficSelector selector2 = nextIdSelectorBuilder(obj.id())
                .matchInPort(port2)
                .build();
        final TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
                .setOutput(port1)
                .build();

        resultBuilder.addFlowRule(flowRule(
                obj, FabricConstants.FABRIC_INGRESS_NEXT_XCONNECT,
                selector1, treatment1));
        resultBuilder.addFlowRule(flowRule(
                obj, FabricConstants.FABRIC_INGRESS_NEXT_XCONNECT,
                selector2, treatment2));

    }

    private void multicastNext(NextObjective obj,
                               ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        // Create ALL group that will be translated to a PRE multicast entry.
        final int groupId = allGroup(obj, resultBuilder);

        if (isGroupModifyOp(obj)) {
            // No changes to flow rules.
            return;
        }

        final TrafficSelector selector = nextIdSelector(obj.id());
        final PiActionParam groupIdParam = new PiActionParam(
                FabricConstants.GROUP_ID, groupId);
        final PiAction setMcGroupAction = PiAction.builder()
                .withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_MCAST_GROUP_ID)
                .withParameter(groupIdParam)
                .build();
        final TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .piTableAction(setMcGroupAction)
                .build();

        resultBuilder.addFlowRule(flowRule(
                obj, FabricConstants.FABRIC_INGRESS_NEXT_MULTICAST,
                selector, treatment));
    }

    private int selectGroup(NextObjective obj,
                            ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        final PiTableId hashedTableId = FabricConstants.FABRIC_INGRESS_NEXT_HASHED;
        final List<DefaultNextTreatment> defaultNextTreatments =
                defaultNextTreatments(obj.nextTreatments(), true);
        final List<TrafficTreatment> piTreatments = Lists.newArrayList();

        for (DefaultNextTreatment t : defaultNextTreatments) {
            // Map treatment to PI...
            piTreatments.add(mapTreatmentToPiIfNeeded(t.treatment(), hashedTableId));
            // ...and handle egress if necessary.
            handleEgress(obj, t.treatment(), resultBuilder, false);
        }

        final List<GroupBucket> bucketList = piTreatments.stream()
                .map(DefaultGroupBucket::createSelectGroupBucket)
                .collect(Collectors.toList());

        final int groupId = obj.id();
        final PiGroupKey groupKey = new PiGroupKey(
                hashedTableId,
                FabricConstants.FABRIC_INGRESS_NEXT_HASHED_SELECTOR,
                groupId);

        resultBuilder.addGroup(new DefaultGroupDescription(
                deviceId,
                GroupDescription.Type.SELECT,
                new GroupBuckets(bucketList),
                groupKey,
                groupId,
                obj.appId()));

        return groupId;
    }

    private int allGroup(NextObjective obj,
                         ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        final Collection<DefaultNextTreatment> defaultNextTreatments =
                defaultNextTreatments(obj.nextTreatments(), true);
        // No need to map treatments to PI as translation of ALL groups to PRE
        // multicast entries is based solely on the output port.
        for (DefaultNextTreatment t : defaultNextTreatments) {
            handleEgress(obj, t.treatment(), resultBuilder, true);
        }

        // FIXME: this implementation supports only the case in which each
        // switch interface is associated with only one VLAN, otherwise we would
        // need to support replicating multiple times the same packet for the
        // same port while setting different VLAN IDs. Hence, collect in a set.
        final Set<PortNumber> outPorts = defaultNextTreatments.stream()
                .map(DefaultNextTreatment::treatment)
                .map(FabricUtils::outputPort)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (outPorts.size() != defaultNextTreatments.size()) {
            throw new FabricPipelinerException(format(
                    "Found BROADCAST NextObjective with %d treatments but " +
                            "found only %d distinct OUTPUT port numbers, cannot " +
                            "translate to ALL groups",
                    defaultNextTreatments.size(), outPorts.size()),
                                               ObjectiveError.UNSUPPORTED);
        }

        final List<GroupBucket> bucketList = outPorts.stream()
                .map(p -> DefaultTrafficTreatment.builder().setOutput(p).build())
                .map(DefaultGroupBucket::createAllGroupBucket)
                .collect(Collectors.toList());
        // FIXME: remove once support for clone sessions is available
        // Right now we add a CPU port to all multicast groups. The egress
        // pipeline is expected to drop replicated packets to the CPU if a clone
        // was  not requested in the ingress pipeline.
        bucketList.add(
                DefaultGroupBucket.createAllGroupBucket(
                        DefaultTrafficTreatment.builder()
                                .setOutput(PortNumber.CONTROLLER)
                                .build()));

        final int groupId = obj.id();
        // Use DefaultGroupKey instead of PiGroupKey as we don't have any
        // action profile to apply to the groups of ALL type.
        final GroupKey groupKey = new DefaultGroupKey(
                FabricPipeliner.KRYO.serialize(groupId));

        resultBuilder.addGroup(
                new DefaultGroupDescription(
                        deviceId,
                        GroupDescription.Type.ALL,
                        new GroupBuckets(bucketList),
                        groupKey,
                        groupId,
                        obj.appId()));

        return groupId;
    }

    private List<DefaultNextTreatment> defaultNextTreatments(
            Collection<NextTreatment> nextTreatments, boolean strict)
            throws FabricPipelinerException {
        final List<DefaultNextTreatment> defaultNextTreatments = Lists.newArrayList();
        final List<NextTreatment> unsupportedNextTreatments = Lists.newArrayList();
        for (NextTreatment n : nextTreatments) {
            if (n.type() == NextTreatment.Type.TREATMENT) {
                defaultNextTreatments.add((DefaultNextTreatment) n);
            } else {
                unsupportedNextTreatments.add(n);
            }
        }
        if (strict && !unsupportedNextTreatments.isEmpty()) {
            throw new FabricPipelinerException(format(
                    "Unsupported NextTreatments: %s",
                    unsupportedNextTreatments));
        }
        return defaultNextTreatments;
    }

    private TrafficTreatment getFirstDefaultNextTreatmentIfAny(
            Collection<NextTreatment> nextTreatments)
            throws FabricPipelinerException {
        final Collection<DefaultNextTreatment> nexts = defaultNextTreatments(nextTreatments, false);
        return nexts.isEmpty() ? null : nexts.iterator().next().treatment();
    }

    private boolean isGroupModifyOp(NextObjective obj) {
        // If operation is ADD_TO_EXIST or REMOVE_FROM_EXIST, it means we modify
        // group buckets only, no changes for flow rules.
        return obj.op() == Objective.Operation.ADD_TO_EXISTING ||
                obj.op() == Objective.Operation.REMOVE_FROM_EXISTING;
    }

    private boolean isXconnect(NextObjective obj) {
        return obj.appId().name().contains(XCONNECT);
    }
}
