/*
 * 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.driver.pipeline;

import org.onlab.packet.Ethernet;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
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.FlowRuleOperations;
import org.onosproject.net.flow.FlowRuleOperationsContext;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
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.Instructions;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.ObjectiveError;
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.slf4j.LoggerFactory.getLogger;

public class CorsaPipelineV3 extends OVSCorsaPipeline {

    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;

    private MeterId defaultMeterId = null;

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

        treatment.immediate().stream()
                .filter(i -> i instanceof L2ModificationInstruction.ModVlanIdInstruction ||
                             i instanceof L2ModificationInstruction.ModEtherInstruction ||
                             i instanceof Instructions.OutputInstruction)
                .forEach(i -> tb.add(i));
        return tb.build();
    }

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

    @Override
    protected FlowRule.Builder processSpecificRoutingRule(FlowRule.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();

        FlowRule.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 void processFilter(FilteringObjective filt, boolean install,
                               ApplicationId applicationId) {
        // This driver only processes filtering criteria defined with switch
        // ports as the key
        PortCriterion p;
        if (!filt.key().equals(Criteria.dummy()) &&
                filt.key().type() == Criterion.Type.IN_PORT) {
            p = (PortCriterion) filt.key();
        } else {
            log.warn("No key defined in filtering objective from app: {}. Not"
                    + "processing filtering objective", applicationId);
            fail(filt, ObjectiveError.UNKNOWN);
            return;
        }
        // convert filtering conditions for switch-intfs into flowrules
        FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
        for (Criterion c : filt.conditions()) {
            if (c.type() == Criterion.Type.ETH_DST) {
                EthCriterion e = (EthCriterion) c;
                log.debug("adding rule for MAC: {}", e.mac());
                TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
                TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
                selector.matchEthDst(e.mac());
                selector.matchInPort(p.port());
                treatment.transition(ETHER_TABLE);
                FlowRule rule = DefaultFlowRule.builder()
                        .forDevice(deviceId)
                        .withSelector(selector.build())
                        .withTreatment(treatment.build())
                        .withPriority(CONTROLLER_PRIORITY)
                        .fromApp(applicationId)
                        .makePermanent()
                        .forTable(L3_IF_MAC_DA_TABLE).build();
                ops =  install ? ops.add(rule) : ops.remove(rule);
            } else if (c.type() == Criterion.Type.VLAN_VID) {
                VlanIdCriterion v = (VlanIdCriterion) c;
                log.debug("adding rule for VLAN: {}", v.vlanId());
                TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
                TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
                selector.matchVlanId(v.vlanId());
                selector.matchInPort(p.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);
                FlowRule rule = DefaultFlowRule.builder()
                        .forDevice(deviceId)
                        .withSelector(selector.build())
                        .withTreatment(treatment.build())
                        .withPriority(CONTROLLER_PRIORITY)
                        .fromApp(applicationId)
                        .makePermanent()
                        .forTable(VLAN_CIRCUIT_TABLE).build();
                ops = install ? ops.add(rule) : ops.remove(rule);
            } else if (c.type() == Criterion.Type.IPV4_DST) {
                IPCriterion ip = (IPCriterion) c;
                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);
                FlowRule rule = DefaultFlowRule.builder()
                        .forDevice(deviceId)
                        .withSelector(selector.build())
                        .withTreatment(treatment.build())
                        .withPriority(HIGHEST_PRIORITY)
                        .fromApp(applicationId)
                        .makePermanent()
                        .forTable(FIB_TABLE).build();

                ops = install ? ops.add(rule) : ops.remove(rule);
            } else {
                log.warn("Driver does not currently process filtering condition"
                        + " of type: {}", c.type());
                fail(filt, ObjectiveError.UNSUPPORTED);
            }
        }
        // apply filtering flow rules
        flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
            @Override
            public void onSuccess(FlowRuleOperations ops) {
                pass(filt);
                log.info("Applied filtering rules");
            }

            @Override
            public void onError(FlowRuleOperations ops) {
                fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
                log.info("Failed to apply filtering rules");
            }
        }));
    }

    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 */
    }

    private 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();
    }

    private void processPortBasedProtoTable(boolean install) {
        /* Default action */
        processTableMissGoTo(install, PORT_BASED_PROTO_TABLE, VLAN_CHECK_TABLE);
    }

    private void processVlanCheckTable(boolean install) {
        int table = VLAN_CHECK_TABLE;

        /* Default action */
        processTableMissDrop(install, table);

        /* Tagged packets to VLAN_MAC_XLATE */
        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(table).build();
        processFlowRule(install, rule);
    }

    private void processVlanMacXlateTable(boolean install) {
        /* Default action */
        processTableMissGoTo(install, VLAN_MAC_XLATE_TABLE, VLAN_CIRCUIT_TABLE);
    }

    private void processVlanCircuitTable(boolean install) {
        /* Default action */
        processTableMissDrop(install, VLAN_CIRCUIT_TABLE);
    }

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

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

        /* Default action */
        processTableMissDrop(install, table);

        /* 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);
    }


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

        /* Default action */
        processTableMissDrop(install, table);

        /* 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);

        /* 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);
    }

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

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

        /* 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);
    }

    /* Init helper: Apply flow rule */
    private void processFlowRule(boolean install, FlowRule rule) {
        FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
        ops = install ? ops.add(rule) : ops.remove(rule);

        flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
            @Override
            public void onSuccess(FlowRuleOperations ops) {
                log.info("Flow provision success: " + ops.toString() + ", " + rule.toString());
            }

            @Override
            public void onError(FlowRuleOperations ops) {
                log.info("Flow provision error: " + ops.toString() + ", " + rule.toString());
            }
        }));
    }

    /* Init helper: Table Miss = Drop */
    private void processTableMissDrop(boolean install, int table) {
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();

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

        FlowRule rule = DefaultFlowRule.builder()
                .forDevice(deviceId)
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(DROP_PRIORITY)
                .fromApp(appId)
                .makePermanent()
                .forTable(table).build();

        processFlowRule(install, rule);
    }

    /* Init helper: Table Miss = GoTo */
    private void processTableMissGoTo(boolean install, int table, int goTo) {
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();

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

        FlowRule rule = DefaultFlowRule.builder()
                .forDevice(deviceId)
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(DROP_PRIORITY)
                .fromApp(appId)
                .makePermanent()
                .forTable(table).build();

        processFlowRule(install, rule);
    }
}
