/*
 * 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.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
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.EthCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.pi.model.PiActionId;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.pipelines.fabric.FabricCapabilities;
import org.onosproject.pipelines.fabric.FabricConstants;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static java.lang.String.format;
import static org.onosproject.pipelines.fabric.FabricUtils.criterionNotNull;

/**
 * ObjectiveTranslator implementation ForwardingObjective.
 */
class ForwardingObjectiveTranslator
        extends AbstractObjectiveTranslator<ForwardingObjective> {

    private static final List<String> DEFAULT_ROUTE_PREFIXES = Lists.newArrayList(
            "0.0.0.0/1", "128.0.0.0/1");

    private static final Set<Criterion.Type> ACL_CRITERIA = ImmutableSet.of(
            Criterion.Type.IN_PORT,
            Criterion.Type.IN_PHY_PORT,
            Criterion.Type.ETH_DST,
            Criterion.Type.ETH_DST_MASKED,
            Criterion.Type.ETH_SRC,
            Criterion.Type.ETH_SRC_MASKED,
            Criterion.Type.ETH_TYPE,
            Criterion.Type.VLAN_VID,
            Criterion.Type.IP_PROTO,
            Criterion.Type.IPV4_SRC,
            Criterion.Type.IPV4_DST,
            Criterion.Type.TCP_SRC,
            Criterion.Type.TCP_SRC_MASKED,
            Criterion.Type.TCP_DST,
            Criterion.Type.TCP_DST_MASKED,
            Criterion.Type.UDP_SRC,
            Criterion.Type.UDP_SRC_MASKED,
            Criterion.Type.UDP_DST,
            Criterion.Type.UDP_DST_MASKED,
            Criterion.Type.ICMPV4_TYPE,
            Criterion.Type.ICMPV4_CODE,
            Criterion.Type.PROTOCOL_INDEPENDENT);

    private static final Map<PiTableId, PiActionId> NEXT_ID_ACTIONS = ImmutableMap.<PiTableId, PiActionId>builder()
            .put(FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING,
                 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_BRIDGING)
            .put(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V4,
                 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_ROUTING_V4)
            .put(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V6,
                 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_ROUTING_V6)
            .put(FabricConstants.FABRIC_INGRESS_FORWARDING_MPLS,
                 FabricConstants.FABRIC_INGRESS_FORWARDING_POP_MPLS_AND_NEXT)
            .build();

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

    @Override
    public ObjectiveTranslation doTranslate(ForwardingObjective obj)
            throws FabricPipelinerException {
        final ObjectiveTranslation.Builder resultBuilder =
                ObjectiveTranslation.builder();
        switch (obj.flag()) {
            case SPECIFIC:
                processSpecificFwd(obj, resultBuilder);
                break;
            case VERSATILE:
                processVersatileFwd(obj, resultBuilder);
                break;
            case EGRESS:
            default:
                log.warn("Unsupported ForwardingObjective type '{}'", obj.flag());
                return ObjectiveTranslation.ofError(ObjectiveError.UNSUPPORTED);
        }
        return resultBuilder.build();
    }

    private void processVersatileFwd(ForwardingObjective obj,
                                     ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        final Set<Criterion.Type> unsupportedCriteria = obj.selector().criteria()
                .stream()
                .map(Criterion::type)
                .filter(t -> !ACL_CRITERIA.contains(t))
                .collect(Collectors.toSet());

        if (!unsupportedCriteria.isEmpty()) {
            throw new FabricPipelinerException(format(
                    "unsupported ACL criteria %s", unsupportedCriteria.toString()));
        }

        aclRule(obj, resultBuilder);
    }

    private void processSpecificFwd(ForwardingObjective obj,
                                    ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        final Set<Criterion> criteriaWithMeta = Sets.newHashSet(obj.selector().criteria());

        // FIXME: Is this really needed? Meta is such an ambiguous field...
        // Why would we match on a META field?
        if (obj.meta() != null) {
            criteriaWithMeta.addAll(obj.meta().criteria());
        }

        final ForwardingFunctionType fft = ForwardingFunctionType.getForwardingFunctionType(obj);

        switch (fft) {
            case UNKNOWN:
                throw new FabricPipelinerException(
                        "unable to detect forwarding function type");
            case L2_UNICAST:
                bridgingRule(obj, criteriaWithMeta, resultBuilder, false);
                break;
            case L2_BROADCAST:
                bridgingRule(obj, criteriaWithMeta, resultBuilder, true);
                break;
            case IPV4_ROUTING:
            case IPV4_ROUTING_MULTICAST:
                ipv4RoutingRule(obj, criteriaWithMeta, resultBuilder);
                break;
            case MPLS_SEGMENT_ROUTING:
                mplsRule(obj, criteriaWithMeta, resultBuilder);
                break;
            case IPV6_ROUTING:
            case IPV6_ROUTING_MULTICAST:
            default:
                throw new FabricPipelinerException(format(
                        "unsupported forwarding function type '%s'",
                        fft));
        }
    }

    private void bridgingRule(ForwardingObjective obj, Set<Criterion> criteriaWithMeta,
                              ObjectiveTranslation.Builder resultBuilder,
                              boolean broadcast)
            throws FabricPipelinerException {

        final VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) criterionNotNull(
                criteriaWithMeta, Criterion.Type.VLAN_VID);
        final TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
                .add(vlanIdCriterion);

        if (!broadcast) {
            final EthCriterion ethDstCriterion = (EthCriterion) criterionNotNull(
                    obj.selector(), Criterion.Type.ETH_DST);
            selector.matchEthDstMasked(ethDstCriterion.mac(), MacAddress.EXACT_MASK);
        }

        resultBuilder.addFlowRule(flowRule(
                obj, FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING, selector.build()));
    }

    private void ipv4RoutingRule(ForwardingObjective obj, Set<Criterion> criteriaWithMeta,
                                 ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {
        final IPCriterion ipDstCriterion = (IPCriterion) criterionNotNull(
                criteriaWithMeta, Criterion.Type.IPV4_DST);

        if (ipDstCriterion.ip().prefixLength() == 0) {
            defaultIpv4Route(obj, resultBuilder);
            return;
        }

        final TrafficSelector selector = DefaultTrafficSelector.builder()
                .add(ipDstCriterion)
                .build();

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

    private void defaultIpv4Route(ForwardingObjective obj,
                                  ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        // Hack to work around the inability to program default rules.
        for (String prefix : DEFAULT_ROUTE_PREFIXES) {
            final TrafficSelector selector = DefaultTrafficSelector.builder()
                    .matchIPDst(IpPrefix.valueOf(prefix)).build();
            resultBuilder.addFlowRule(flowRule(
                    obj, FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V4, selector));
        }
    }

    private void mplsRule(ForwardingObjective obj, Set<Criterion> criteriaWithMeta,
                          ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

        final MplsCriterion mplsCriterion = (MplsCriterion) criterionNotNull(
                criteriaWithMeta, Criterion.Type.MPLS_LABEL);
        final TrafficSelector selector = DefaultTrafficSelector.builder()
                .add(mplsCriterion)
                .build();

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

    private void aclRule(ForwardingObjective obj,
                         ObjectiveTranslation.Builder resultBuilder)
            throws FabricPipelinerException {

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

    private FlowRule flowRule(
            ForwardingObjective obj, PiTableId tableId, TrafficSelector selector)
            throws FabricPipelinerException {
        return flowRule(obj, tableId, selector, nextIdOrTreatment(obj, tableId));
    }

    private static TrafficTreatment nextIdOrTreatment(
            ForwardingObjective obj, PiTableId tableId)
            throws FabricPipelinerException {
        if (obj.nextId() == null) {
            return obj.treatment();
        } else {
            if (!NEXT_ID_ACTIONS.containsKey(tableId)) {
                throw new FabricPipelinerException(format(
                        "BUG? no next_id action set for table %s", tableId));
            }
            return DefaultTrafficTreatment.builder()
                    .piTableAction(
                            setNextIdAction(obj.nextId(),
                                            NEXT_ID_ACTIONS.get(tableId)))
                    .build();
        }
    }

    private static PiAction setNextIdAction(Integer nextId, PiActionId actionId) {
        final PiActionParam nextIdParam = new PiActionParam(FabricConstants.NEXT_ID, nextId);
        return PiAction.builder()
                .withId(actionId)
                .withParameter(nextIdParam)
                .build();
    }
}
