/*
 * 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
    static final byte FWD_BRIDGING = 0;
    static final byte FWD_MPLS = 1;
    static final byte FWD_IPV4_ROUTING = 2;
    static final byte FWD_IPV6_ROUTING = 3;
    private static final PiCriterion VLAN_VALID = PiCriterion.builder()
            .matchExact(FabricConstants.HDR_VLAN_TAG_IS_VALID, new byte[]{1})
            .build();
    private static final PiCriterion VLAN_INVALID = PiCriterion.builder()
            .matchExact(FabricConstants.HDR_VLAN_TAG_IS_VALID, 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);
        EthCriterion ethDstMaskedCriterion = filterObjective.conditions().stream()
                .filter(criterion -> criterion.type() == Criterion.Type.ETH_DST_MASKED)
                .map(criterion -> (EthCriterion) criterion)
                .findFirst()
                .orElse(null);

        FlowRule inPortVlanTableRule = createInPortVlanTable(inPortCriterion, vlanCriterion,
                                                             filterObjective);
        Collection<FlowRule> fwdClassifierRules = createFwdClassifierRules(inPortCriterion, ethDstCriterion,
                                                                           ethDstMaskedCriterion, 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.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN)
                .forDevice(deviceId)
                .makePermanent()
                .build();
    }

    private Collection<FlowRule> createFwdClassifierRules(PortCriterion inPortCriterion,
                                                          EthCriterion ethDstCriterion,
                                                          EthCriterion ethDstMaskedCriterion,
                                                          FilteringObjective filterObjective) {
        PortNumber port = inPortCriterion.port();

        Collection<FlowRule> flowRules = Lists.newArrayList();
        if (ethDstCriterion == null) {
            if (ethDstMaskedCriterion == null) {
                // Bridging table, do nothing
                return flowRules;
            }
            // Masked fwd classifier rule
            MacAddress dstMac = ethDstMaskedCriterion.mac();
            MacAddress dstMacMask = ethDstMaskedCriterion.mask();
            FlowRule flow = createMaskedFwdClassifierRule(port, dstMac, dstMacMask, filterObjective);
            if (flow != null) {
                flowRules.add(flow);
            }
            return flowRules;
        }
        MacAddress dstMac = ethDstCriterion.mac();
        flowRules.addAll(createIpFwdClassifierRules(port, dstMac, filterObjective));
        flowRules.add(createMplsFwdClassifierRule(port, dstMac, filterObjective));
        return flowRules;
    }

    private FlowRule createMaskedFwdClassifierRule(PortNumber inPort, MacAddress dstMac, MacAddress dstMacMask,
                                                   FilteringObjective filterObjective) {
        TrafficTreatment treatment;
        short ethType;
        if (dstMac.equals(MacAddress.IPV4_MULTICAST) && dstMacMask.equals(MacAddress.IPV4_MULTICAST_MASK)) {
            treatment = createFwdClassifierTreatment(FWD_IPV4_ROUTING);
            ethType = Ethernet.TYPE_IPV4;
        } else if (dstMac.equals(MacAddress.IPV6_MULTICAST) && dstMacMask.equals(MacAddress.IPV6_MULTICAST_MASK)) {
            treatment = createFwdClassifierTreatment(FWD_IPV6_ROUTING);
            ethType = Ethernet.TYPE_IPV6;
        } else {
            log.warn("Unsupported masked fwd classifier rule. mac={}. mask={}", dstMac, dstMacMask);
            return null;
        }
        return createFwdClassifierRule(inPort, ethType, dstMac, dstMacMask, treatment, filterObjective);
    }

    private Collection<FlowRule> createIpFwdClassifierRules(PortNumber inPort,
                                                            MacAddress dstMac,
                                                            FilteringObjective filterObjective) {
        Collection<FlowRule> flowRules = Lists.newArrayList();
        TrafficTreatment treatment;
        treatment = createFwdClassifierTreatment(FWD_IPV4_ROUTING);
        flowRules.add(createFwdClassifierRule(inPort, Ethernet.TYPE_IPV4, dstMac, null, treatment, filterObjective));
        treatment = createFwdClassifierTreatment(FWD_IPV6_ROUTING);
        flowRules.add(createFwdClassifierRule(inPort, Ethernet.TYPE_IPV6, dstMac, null, 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, null, treatment, filterObjective);
    }

    private FlowRule createFwdClassifierRule(PortNumber inPort,
                                             short ethType,
                                             MacAddress dstMac,
                                             MacAddress dstMacMask,
                                             TrafficTreatment treatment,
                                             FilteringObjective filterObjective) {
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
                .matchInPort(inPort)
                .matchEthType(ethType);
        if (dstMacMask != null) {
            selector.matchEthDstMasked(dstMac, dstMacMask);
        } else {
            selector.matchEthDstMasked(dstMac, MacAddress.EXACT_MASK);
        }

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

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

    }
}
