/*
 * 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.Ethernet;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
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.PiCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flowobjective.FilteringObjective;
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.Collection;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Handling filtering objective for fabric pipeliner.
 */
public class FabricFilteringPipeliner {
    private static final Logger log = getLogger(FabricFilteringPipeliner.class);
    // Forwarding types
    private static final byte FWD_BRIDGING = 0;
    private static final byte FWD_MPLS = 1;
    private static final byte FWD_IPV4_UNICAST = 2;
    private static final byte FWD_IPV4_MULTICAST = 3;
    private static final byte FWD_IPV6_UNICAST = 4;
    private static final byte FWD_IPV6_MULTICAST = 5;
    private static final PiCriterion VLAN_VALID = PiCriterion.builder()
            .matchExact(FabricConstants.HF_VLAN_TAG_IS_VALID_ID, new byte[]{1})
            .build();
    private static final PiCriterion VLAN_INVALID = PiCriterion.builder()
            .matchExact(FabricConstants.HF_VLAN_TAG_IS_VALID_ID, new byte[]{0})
            .build();

    protected DeviceId deviceId;

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

    /**
     * Translates filtering objective to flows and groups.
     *
     * @param filterObjective the filtering objective
     * @return translation result, contains flows, groups or error it generated
     */
    public PipelinerTranslationResult filter(FilteringObjective filterObjective) {
        PipelinerTranslationResult.Builder resultBuilder = PipelinerTranslationResult.builder();
        // maps selector and treatment from filtering objective to filtering
        // control block.

        if (filterObjective.type() == FilteringObjective.Type.DENY) {
            log.warn("Unsupported filtering objective type {}", filterObjective.type());
            resultBuilder.setError(ObjectiveError.UNSUPPORTED);
            return resultBuilder.build();
        }

        if (filterObjective.key() == null ||
                filterObjective.key().type() != Criterion.Type.IN_PORT) {
            log.warn("Unsupported filter key {}", filterObjective.key());
            resultBuilder.setError(ObjectiveError.BADPARAMS);
            return resultBuilder.build();
        }
        PortCriterion inPortCriterion = (PortCriterion) filterObjective.key();
        VlanIdCriterion vlanCriterion = filterObjective.conditions().stream()
                .filter(criterion -> criterion.type() == Criterion.Type.VLAN_VID)
                .map(criterion -> (VlanIdCriterion) criterion)
                .findFirst()
                .orElse(null);
        EthCriterion ethDstCriterion = filterObjective.conditions().stream()
                .filter(criterion -> criterion.type() == Criterion.Type.ETH_DST)
                .map(criterion -> (EthCriterion) criterion)
                .findFirst()
                .orElse(null);

        FlowRule inPortVlanTableRule = createInPortVlanTable(inPortCriterion, vlanCriterion,
                                                             filterObjective);
        Collection<FlowRule> fwdClassifierRules = createFwdClassifierRules(inPortCriterion, ethDstCriterion,
                                                                           filterObjective);

        resultBuilder.addFlowRule(inPortVlanTableRule);
        fwdClassifierRules.forEach(resultBuilder::addFlowRule);
        return resultBuilder.build();
    }

    private FlowRule createInPortVlanTable(Criterion inPortCriterion,
                                           VlanIdCriterion vlanCriterion,
                                           FilteringObjective filterObjective) {
        Criterion vlanIsVlalidCriterion;
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
                .add(inPortCriterion);

        VlanId vlanId = null;
        if (vlanCriterion != null) {
            vlanId = vlanCriterion.vlanId();
        }

        vlanIsVlalidCriterion = VLAN_VALID;
        if (vlanId == null || vlanId.equals(VlanId.NONE)) {
            // untag vlan, match in port only
            vlanIsVlalidCriterion = VLAN_INVALID;
        }

        selector.add(vlanIsVlalidCriterion);

        // TODO: check if this treatment is valid or not
        TrafficTreatment treatment = filterObjective.meta();
        if (treatment == null) {
            treatment = DefaultTrafficTreatment.emptyTreatment();
        }

        return DefaultFlowRule.builder()
                .fromApp(filterObjective.appId())
                .withPriority(filterObjective.priority())
                .withSelector(selector.build())
                .withTreatment(treatment)
                .withPriority(filterObjective.priority())
                .forTable(FabricConstants.TBL_INGRESS_PORT_VLAN_ID)
                .forDevice(deviceId)
                .makePermanent()
                .build();
    }

    private Collection<FlowRule> createFwdClassifierRules(PortCriterion inPortCriterion,
                                                          EthCriterion ethDstCriterion,
                                                          FilteringObjective filterObjective) {
        Collection<FlowRule> flowRules = Lists.newArrayList();
        if (ethDstCriterion == null) {
            // Bridging table, do nothing
            return flowRules;
        }
        PortNumber port = inPortCriterion.port();
        MacAddress dstMac = ethDstCriterion.mac();
        if (dstMac.isMulticast()) {
            flowRules.add(createMulticastFwdClassifierRule(port, dstMac, filterObjective));
            return flowRules;
        }

        flowRules.addAll(createIpFwdClassifierRules(port, dstMac, filterObjective));
        flowRules.add(createMplsFwdClassifierRule(port, dstMac, filterObjective));
        return flowRules;
    }

    private FlowRule createMulticastFwdClassifierRule(PortNumber inPort, MacAddress dstMac,
                                                      FilteringObjective filterObjective) {
        TrafficTreatment treatment;
        short ethType;
        if (dstMac.equals(MacAddress.IPV4_MULTICAST)) {
            // Ipv4 multicast
            treatment = createFwdClassifierTreatment(FWD_IPV4_MULTICAST);
            ethType = Ethernet.TYPE_IPV4;
        } else {
            // IPv6 multicast
            treatment = createFwdClassifierTreatment(FWD_IPV6_MULTICAST);
            ethType = Ethernet.TYPE_IPV6;
        }
        return createFwdClassifierRule(inPort, ethType, dstMac, treatment, filterObjective);
    }

    private Collection<FlowRule> createIpFwdClassifierRules(PortNumber inPort,
                                                            MacAddress dstMac,
                                                            FilteringObjective filterObjective) {
        Collection<FlowRule> flowRules = Lists.newArrayList();
        TrafficTreatment treatment;
        treatment = createFwdClassifierTreatment(FWD_IPV4_UNICAST);
        flowRules.add(createFwdClassifierRule(inPort, Ethernet.TYPE_IPV4, dstMac, treatment, filterObjective));
        treatment = createFwdClassifierTreatment(FWD_IPV6_UNICAST);
        flowRules.add(createFwdClassifierRule(inPort, Ethernet.TYPE_IPV6, dstMac, treatment, filterObjective));
        return flowRules;
    }

    private FlowRule createMplsFwdClassifierRule(PortNumber inPort,
                                                 MacAddress dstMac,
                                                 FilteringObjective filterObjective) {
        TrafficTreatment treatment = createFwdClassifierTreatment(FWD_MPLS);
        return createFwdClassifierRule(inPort, Ethernet.MPLS_UNICAST, dstMac, treatment, filterObjective);
    }

    private FlowRule createFwdClassifierRule(PortNumber inPort,
                                             short ethType,
                                             MacAddress dstMac,
                                             TrafficTreatment treatment,
                                             FilteringObjective filterObjective) {
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
                .matchInPort(inPort)
                .matchEthDst(dstMac)
                .matchEthType(ethType);

        return DefaultFlowRule.builder()
                .withSelector(selector.build())
                .withTreatment(treatment)
                .fromApp(filterObjective.appId())
                .withPriority(filterObjective.priority())
                .forDevice(deviceId)
                .makePermanent()
                .forTable(FabricConstants.TBL_FWD_CLASSIFIER_ID)
                .build();
    }

    private TrafficTreatment createFwdClassifierTreatment(byte fwdType) {
        PiActionParam param = new PiActionParam(FabricConstants.ACT_PRM_FWD_TYPE_ID,
                                                ImmutableByteSequence.copyFrom(fwdType));
        PiAction action = PiAction.builder()
                .withId(FabricConstants.ACT_FABRICINGRESS_FILTERING_SET_FORWARDING_TYPE_ID)
                .withParameter(param)
                .build();
        return DefaultTrafficTreatment.builder()
                .piTableAction(action)
                .build();

    }
}
