/*
 * 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.ImmutableSet;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.DefaultFlowRule;
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.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.pipelines.fabric.FabricConstants;
import org.slf4j.Logger;

import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Handling forwarding objective for fabric pipeliner.
 */
public class FabricForwardingPipeliner {
    private static final Logger log = getLogger(FabricForwardingPipeliner.class);

    protected DeviceId deviceId;

    public FabricForwardingPipeliner(DeviceId deviceId) {
        this.deviceId = deviceId;
    }

    public PipelinerTranslationResult forward(ForwardingObjective forwardObjective) {
        PipelinerTranslationResult.Builder resultBuilder = PipelinerTranslationResult.builder();
        if (forwardObjective.flag() == ForwardingObjective.Flag.VERSATILE) {
            processVersatileFwd(forwardObjective, resultBuilder);
        } else {
            processSpecificFwd(forwardObjective, resultBuilder);
        }
        return resultBuilder.build();
    }

    private void processVersatileFwd(ForwardingObjective fwd,
                                     PipelinerTranslationResult.Builder resultBuilder) {
        // TODO: Move IPv6 match to different ACL table

        boolean unsupported = fwd.selector().criteria().stream()
                .anyMatch(criterion -> criterion.type() == Criterion.Type.IPV6_DST);
        unsupported |= fwd.selector().criteria().stream()
                .anyMatch(criterion -> criterion.type() == Criterion.Type.IPV6_SRC);

        if (unsupported) {
            resultBuilder.setError(ObjectiveError.UNSUPPORTED);
            return;
        }

        // program ACL table only
        FlowRule flowRule = DefaultFlowRule.builder()
                .withSelector(fwd.selector())
                .withTreatment(fwd.treatment())
                .forTable(FabricConstants.TBL_ACL_ID)
                .withPriority(fwd.priority())
                .forDevice(deviceId)
                .makePermanent()
                .fromApp(fwd.appId())
                .build();
        resultBuilder.addFlowRule(flowRule);
    }

    private void processSpecificFwd(ForwardingObjective fwd,
                                    PipelinerTranslationResult.Builder resultBuilder) {
        TrafficSelector selector = fwd.selector();
        TrafficSelector meta = fwd.meta();

        ImmutableSet.Builder<Criterion> criterionSetBuilder = ImmutableSet.builder();
        criterionSetBuilder.addAll(selector.criteria());

        if (meta != null) {
            criterionSetBuilder.addAll(meta.criteria());
        }

        Set<Criterion> criteria = criterionSetBuilder.build();

        VlanIdCriterion vlanIdCriterion = null;
        EthCriterion ethDstCriterion = null;
        IPCriterion ipDstCriterion = null;
        MplsCriterion mplsCriterion = null;

        for (Criterion criterion : criteria) {
            switch (criterion.type()) {
                case ETH_DST:
                    ethDstCriterion = (EthCriterion) criterion;
                    break;
                case VLAN_VID:
                    vlanIdCriterion = (VlanIdCriterion) criterion;
                    break;
                case IPV4_DST:
                    ipDstCriterion = (IPCriterion) criterion;
                    break;
                case MPLS_LABEL:
                    mplsCriterion = (MplsCriterion) criterion;
                    break;
                case ETH_TYPE:
                case MPLS_BOS:
                    // do nothing
                    break;
                default:
                    log.warn("Unsupported criterion {}", criterion);
                    break;
            }
        }

        ForwardingFunctionType forwardingFunctionType =
                ForwardingFunctionType.getForwardingFunctionType(fwd);
        switch (forwardingFunctionType) {
            case L2_UNICAST:
                processL2UnicastRule(vlanIdCriterion, ethDstCriterion, fwd, resultBuilder);
                break;
            case L2_BROADCAST:
                processL2BroadcastRule(vlanIdCriterion, fwd, resultBuilder);
                break;
            case IPV4_UNICAST:
                processIpv4UnicastRule(ipDstCriterion, fwd, resultBuilder);
                break;
            case MPLS:
                processMplsRule(mplsCriterion, fwd, resultBuilder);
                break;
            case IPV4_MULTICAST:
            case IPV6_UNICAST:
            case IPV6_MULTICAST:
            default:
                log.warn("Unsupported forwarding function type {}", criteria);
                resultBuilder.setError(ObjectiveError.UNSUPPORTED);
                break;
        }
    }

    // L2 Unicast: learnt mac address + vlan
    private void processL2UnicastRule(VlanIdCriterion vlanIdCriterion,
                                      EthCriterion ethDstCriterion,
                                      ForwardingObjective fwd,
                                      PipelinerTranslationResult.Builder resultBuilder) {
        checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
        checkNotNull(ethDstCriterion, "EthDst criterion should not be null");

        VlanId vlanId = vlanIdCriterion.vlanId();
        MacAddress ethDst = ethDstCriterion.mac();

        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchVlanId(vlanId)
                .matchEthDst(ethDst)
                .build();
        TrafficTreatment treatment = fwd.treatment();
        if (fwd.nextId() != null) {
            treatment = buildSetNextIdTreatment(fwd.nextId());
        }

        FlowRule flowRule = DefaultFlowRule.builder()
                .withSelector(selector)
                .withTreatment(treatment)
                .fromApp(fwd.appId())
                .withPriority(fwd.priority())
                .makePermanent()
                .forDevice(deviceId)
                .forTable(FabricConstants.TBL_BRIDGING_ID)
                .build();

        resultBuilder.addFlowRule(flowRule);
    }

    private void processL2BroadcastRule(VlanIdCriterion vlanIdCriterion,
                                        ForwardingObjective fwd,
                                        PipelinerTranslationResult.Builder resultBuilder) {
        checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");

        VlanId vlanId = vlanIdCriterion.vlanId();

        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchVlanId(vlanId)
                .build();
        TrafficTreatment treatment = fwd.treatment();
        if (fwd.nextId() != null) {
            treatment = buildSetNextIdTreatment(fwd.nextId());
        }
        FlowRule flowRule = DefaultFlowRule.builder()
                .withSelector(selector)
                .withTreatment(treatment)
                .fromApp(fwd.appId())
                .withPriority(fwd.priority())
                .makePermanent()
                .forDevice(deviceId)
                .forTable(FabricConstants.TBL_BRIDGING_ID)
                .build();

        resultBuilder.addFlowRule(flowRule);
    }

    private void processIpv4UnicastRule(IPCriterion ipDstCriterion, ForwardingObjective fwd,
                                        PipelinerTranslationResult.Builder resultBuilder) {
        checkNotNull(ipDstCriterion, "IP dst criterion should not be null");
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchIPDst(ipDstCriterion.ip())
                .build();
        TrafficTreatment treatment = fwd.treatment();
        if (fwd.nextId() != null) {
            treatment = buildSetNextIdTreatment(fwd.nextId());
        }
        FlowRule flowRule = DefaultFlowRule.builder()
                .withSelector(selector)
                .withTreatment(treatment)
                .fromApp(fwd.appId())
                .withPriority(fwd.priority())
                .makePermanent()
                .forDevice(deviceId)
                .forTable(FabricConstants.TBL_UNICAST_V4_ID)
                .build();

        resultBuilder.addFlowRule(flowRule);
    }

    private void processMplsRule(MplsCriterion mplsCriterion, ForwardingObjective fwd,
                                 PipelinerTranslationResult.Builder resultBuilder) {
        checkNotNull(mplsCriterion, "Mpls criterion should not be null");
        TrafficTreatment treatment;

        treatment = fwd.treatment();
        if (fwd.nextId() != null) {
            PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
                                                          ImmutableByteSequence.copyFrom(fwd.nextId().byteValue()));
            PiAction nextIdAction = PiAction.builder()
                    .withId(FabricConstants.ACT_FABRICINGRESS_FORWARDING_POP_MPLS_AND_NEXT_ID)
                    .withParameter(nextIdParam)
                    .build();
            treatment = DefaultTrafficTreatment.builder()
                    .piTableAction(nextIdAction)
                    .build();
        }

        TrafficSelector selector = DefaultTrafficSelector.builder()
                .add(mplsCriterion)
                .build();

        FlowRule flowRule = DefaultFlowRule.builder()
                .withSelector(selector)
                .withTreatment(treatment)
                .fromApp(fwd.appId())
                .withPriority(fwd.priority())
                .makePermanent()
                .forDevice(deviceId)
                .forTable(FabricConstants.TBL_MPLS_ID)
                .build();

        resultBuilder.addFlowRule(flowRule);
    }

    /**
     * Builds treatment with set_next_id action, returns empty treatment
     * if next id is null.
     *
     * @param nextId the next id for action
     * @return treatment with set_next_id action; empty treatment if next id is null
     */
    private static TrafficTreatment buildSetNextIdTreatment(Integer nextId) {
        PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
                                                      ImmutableByteSequence.copyFrom(nextId.byteValue()));
        PiAction nextIdAction = PiAction.builder()
                .withId(FabricConstants.ACT_FABRICINGRESS_FORWARDING_SET_NEXT_ID_ID)
                .withParameter(nextIdParam)
                .build();

        return DefaultTrafficTreatment.builder()
                .piTableAction(nextIdAction)
                .build();
    }
}
