/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * 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.drivers.corsa;

import org.onlab.packet.Ethernet;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
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.PortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.meter.Band;
import org.onosproject.net.meter.DefaultBand;
import org.onosproject.net.meter.DefaultMeterRequest;
import org.onosproject.net.meter.Meter;
import org.onosproject.net.meter.MeterId;
import org.onosproject.net.meter.MeterRequest;
import org.slf4j.Logger;

import java.util.Collection;
import java.util.Collections;

import static org.onosproject.net.flow.FlowRule.Builder;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Implementation of the Corsa pipeline handler for pipeline version 3.
 */
public class CorsaPipelineV3 extends AbstractCorsaPipeline {

    private final Logger log = getLogger(getClass());

    protected static final int PORT_BASED_PROTO_TABLE = 0;
    protected static final int VLAN_CHECK_TABLE = 1;
    protected static final int VLAN_MAC_XLATE_TABLE = 2;
    protected static final int VLAN_CIRCUIT_TABLE = 3;
    protected static final int PRIORITY_MAP_TABLE = 4;
    protected static final int L3_IF_MAC_DA_TABLE = 5;
    protected static final int ETHER_TABLE = 6;
    protected static final int FIB_TABLE = 7;
    protected static final int LOCAL_TABLE = 9;

    protected static final byte MAX_VLAN_PCP = 7;

    protected MeterId defaultMeterId = null;

    @Override
    protected TrafficTreatment processNextTreatment(TrafficTreatment treatment) {
        TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();

        treatment.immediate().stream()
                .filter(i -> {
                    switch (i.type()) {
                        case L2MODIFICATION:
                            L2ModificationInstruction l2i = (L2ModificationInstruction) i;
                            if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction ||
                                    l2i instanceof L2ModificationInstruction.ModEtherInstruction) {
                                return true;
                            }
                        case OUTPUT:
                            return true;
                        default:
                            return false;
                    }
                }).forEach(i -> tb.add(i));
        return tb.build();
    }

    @Override
    protected TrafficTreatment.Builder processSpecificRoutingTreatment() {
        return DefaultTrafficTreatment.builder().deferred();
    }

    @Override
    protected Builder processSpecificRoutingRule(Builder rb) {
        return rb.forTable(FIB_TABLE);
    }

    @Override
    protected Collection<FlowRule> processSpecificSwitch(ForwardingObjective fwd) {
        TrafficSelector filteredSelector =
                DefaultTrafficSelector.builder()
                        .matchInPort(
                                ((PortCriterion) fwd.selector().getCriterion(Criterion.Type.IN_PORT)).port())
                        .matchVlanId(
                                ((VlanIdCriterion) fwd.selector().getCriterion(Criterion.Type.VLAN_VID)).vlanId())
                        .build();

        Builder ruleBuilder = DefaultFlowRule.builder()
                .fromApp(fwd.appId())
                .withPriority(fwd.priority())
                .forDevice(deviceId)
                .withSelector(filteredSelector)
                .withTreatment(fwd.treatment())
                .forTable(VLAN_CIRCUIT_TABLE);

        if (fwd.permanent()) {
            ruleBuilder.makePermanent();
        } else {
            ruleBuilder.makeTemporary(fwd.timeout());
        }

        return Collections.singletonList(ruleBuilder.build());
    }

    @Override
    protected Collection<FlowRule> processArpTraffic(ForwardingObjective fwd, Builder rule) {
        //TODO
        return Collections.emptyList();
    }

    @Override
    protected Collection<FlowRule> processLinkDiscovery(ForwardingObjective fwd, Builder rule) {
        //TODO
        return Collections.emptyList();
    }

    @Override
    protected Collection<FlowRule> processIpTraffic(ForwardingObjective fwd, Builder rule) {
        //TODO
        return Collections.emptyList();
    }

    @Override
    protected Builder processEthFiler(FilteringObjective filt, EthCriterion eth, PortCriterion port) {
                         log.debug("adding rule for MAC: {}", eth.mac());
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        selector.matchEthDst(eth.mac());
        selector.matchInPort(port.port());
        treatment.transition(ETHER_TABLE);
        return DefaultFlowRule.builder()
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(CONTROLLER_PRIORITY)
                .makePermanent()
                .forTable(L3_IF_MAC_DA_TABLE);
    }

    @Override
    protected Builder processVlanFiler(FilteringObjective filt, VlanIdCriterion vlan, PortCriterion port) {
        log.debug("adding rule for VLAN: {}", vlan.vlanId());
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        selector.matchVlanId(vlan.vlanId());
        selector.matchInPort(port.port());
                /* Static treatment for VLAN_CIRCUIT_TABLE */
        treatment.setVlanPcp(MAX_VLAN_PCP);
        treatment.setQueue(0);
        treatment.meter(MeterId.meterId(defaultMeterId.id())); /* use default meter (Green) */
        treatment.transition(L3_IF_MAC_DA_TABLE);
        return DefaultFlowRule.builder()
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(CONTROLLER_PRIORITY)
                .makePermanent()
                .forTable(VLAN_CIRCUIT_TABLE);
    }

    @Override
    protected Builder processIpFilter(FilteringObjective filt, IPCriterion ip, PortCriterion port) {
        log.debug("adding rule for IP: {}", ip.ip());
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        selector.matchEthType(Ethernet.TYPE_IPV4);
        selector.matchIPDst(ip.ip());
        treatment.transition(LOCAL_TABLE);
        return DefaultFlowRule.builder()
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(HIGHEST_PRIORITY)
                .makePermanent()
                .forTable(FIB_TABLE);
    }

    @Override
    public void initializePipeline() {
        processMeterTable(true);
        processPortBasedProtoTable(true); /* Table 0 */
        processVlanCheckTable(true);      /* Table 1 */
        processVlanMacXlateTable(true);   /* Table 2 */
        processVlanCircuitTable(true);    /* Table 3 */
        processPriorityMapTable(true);    /* Table 4 */
        processL3IFMacDATable(true);      /* Table 5 */
        processEtherTable(true);          /* Table 6 */
        processFibTable(true);            /* Table 7 */
        processLocalTable(true);          /* Table 9 */
    }

    protected void processMeterTable(boolean install) {
        //Green meter : Pass all traffic
        Band dropBand = DefaultBand.builder()
                .ofType(Band.Type.DROP)
                .withRate(0xFFFFFFFF)   /* Max Rate */
                .build();
        MeterRequest.Builder ops = DefaultMeterRequest.builder()
                .forDevice(deviceId)
                .withBands(Collections.singletonList(dropBand))
                .fromApp(appId);

        Meter meter = meterService.submit(install ? ops.add() : ops.remove());
        defaultMeterId = meter.id();
    }

    protected void processPortBasedProtoTable(boolean install) {
        /* Default action */
        processTableMissGoTo(install, PORT_BASED_PROTO_TABLE, VLAN_CHECK_TABLE, "Provisioned port-based table");
    }

    protected void processVlanCheckTable(boolean install) {

        /* Default action */
        processTableMissDrop(install, VLAN_CHECK_TABLE, "Provisioned vlantable drop");

        processTaggedPackets(install);

    }

    /* Tagged packets to VLAN_MAC_XLATE */
    protected void processTaggedPackets(boolean install) {
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.matchVlanId(VlanId.ANY);

        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        treatment.transition(VLAN_MAC_XLATE_TABLE);

        FlowRule rule = DefaultFlowRule.builder()
                .forDevice(deviceId)
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(CONTROLLER_PRIORITY)
                .fromApp(appId)
                .makePermanent()
                .forTable(VLAN_CHECK_TABLE).build();
        processFlowRule(install, rule, "Provisioned vlan table tagged packets");
    }

    protected void processVlanMacXlateTable(boolean install) {
        /* Default action */
        processTableMissGoTo(install, VLAN_MAC_XLATE_TABLE, VLAN_CIRCUIT_TABLE, "Provisioned vlan mac table");
    }

    protected void processVlanCircuitTable(boolean install) {
        /* Default action */
        processTableMissDrop(install, VLAN_CIRCUIT_TABLE, "Provisioned vlan circuit");
    }

    private void processPriorityMapTable(boolean install) {
        /* Not required currently */
    }

    protected void processL3IFMacDATable(boolean install) {
        int table = L3_IF_MAC_DA_TABLE;

        /* Default action */
        processTableMissDrop(install, table, "Provisioned l3 table drop");

        /* Allow MAC broadcast frames on all ports */
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.matchEthDst(MacAddress.BROADCAST);

        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        treatment.transition(ETHER_TABLE);

        FlowRule rule = DefaultFlowRule.builder()
                .forDevice(deviceId)
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(CONTROLLER_PRIORITY)
                .fromApp(appId)
                .makePermanent()
                .forTable(table).build();
        processFlowRule(install, rule, "Provisioned l3 table");
    }


    protected void processEtherTable(boolean install) {
        int table = ETHER_TABLE;

        /* Default action */
        processTableMissDrop(install, table, "Provisioned ether type table drop");

        /* Arp to controller */
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.matchEthType(Ethernet.TYPE_ARP);

        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        treatment.punt();

        FlowRule rule = DefaultFlowRule.builder()
                .forDevice(deviceId)
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(CONTROLLER_PRIORITY)
                .fromApp(appId)
                .makePermanent()
                .forTable(table).build();
        processFlowRule(install, rule, "Provisioned ether type table arp");

        /* IP to FIB_TABLE */
        selector = DefaultTrafficSelector.builder();
        selector.matchEthType(Ethernet.TYPE_IPV4);

        treatment = DefaultTrafficTreatment.builder();
        treatment.transition(FIB_TABLE);

        rule = DefaultFlowRule.builder()
                .forDevice(deviceId)
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(CONTROLLER_PRIORITY)
                .fromApp(appId)
                .makePermanent()
                .forTable(table).build();
        processFlowRule(install, rule, "Provisioned ether type table ip");
    }

    private void processFibTable(boolean install) {
        /* Default action */
        processTableMissDrop(install, FIB_TABLE, "Provisioned fib drop");
    }

    private void processLocalTable(boolean install) {
        int table = LOCAL_TABLE;
        /* Default action */
        processTableMissDrop(install, table, "Provisioned local table drop");

        /* Send all protocols to controller */
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();

        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        treatment.punt();

        FlowRule rule = DefaultFlowRule.builder()
                .forDevice(deviceId)
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(CONTROLLER_PRIORITY)
                .fromApp(appId)
                .makePermanent()
                .forTable(table).build();
        processFlowRule(install, rule, "Provisioned ether type table to controller");
    }


}
