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

import com.google.common.collect.ImmutableSet;
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.Instruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;
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.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 CorsaTrafficTreatment processNextTreatment(TrafficTreatment treatment) {
        TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();



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

        TrafficTreatment t = tb.build();


        boolean isPresentModVlanId = false;
        boolean isPresentModEthSrc = false;
        boolean isPresentModEthDst = false;
        boolean isPresentOutpuPort = false;

        for (Instruction instruction : t.immediate()) {
            switch (instruction.type()) {
                case L2MODIFICATION:
                    L2ModificationInstruction l2i = (L2ModificationInstruction) instruction;
                    if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction) {
                        isPresentModVlanId = true;
                    }

                    if (l2i instanceof L2ModificationInstruction.ModEtherInstruction) {
                        L2ModificationInstruction.L2SubType subType = l2i.subtype();
                        if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC)) {
                            isPresentModEthSrc = true;
                        } else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST)) {
                            isPresentModEthDst = true;
                        }
                    }
                    break;
                case OUTPUT:
                    isPresentOutpuPort = true;
                    break;
                default:
            }
        }
        CorsaTrafficTreatmentType type = CorsaTrafficTreatmentType.ACTIONS;
        /**
         * This represents the allowed group for CorsaPipelinev3
         */
        if (isPresentModVlanId &&
                isPresentModEthSrc &&
                isPresentModEthDst &&
                isPresentOutpuPort) {
            type = CorsaTrafficTreatmentType.GROUP;
        }
        CorsaTrafficTreatment corsaTreatment = new CorsaTrafficTreatment(type, t);
        return corsaTreatment;
    }

    @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)
                .forTable(VLAN_CIRCUIT_TABLE);

        if (fwd.treatment() != null) {
            ruleBuilder.withTreatment(fwd.treatment());
        } else {
            if (fwd.nextId() != null) {
                NextObjective nextObjective = pendingNext.getIfPresent(fwd.nextId());
                if (nextObjective != null) {
                    pendingNext.invalidate(fwd.nextId());
                    TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
                            .setVlanPcp((byte) 0)
                            .setQueue(0)
                            .meter(defaultMeterId);
                    nextObjective.next().forEach(trafficTreatment -> {
                        trafficTreatment.allInstructions().forEach(instruction -> {
                           treatment.add(instruction);
                        });
                    });
                    ruleBuilder.withTreatment(treatment.build());
                } else {
                    log.warn("The group left!");
                    fwd.context().ifPresent(c -> c.onError(fwd, ObjectiveError.GROUPMISSING));
                    return ImmutableSet.of();
                }
            } else {
                log.warn("Missing NextObjective ID for ForwardingObjective {}", fwd.id());
                fail(fwd, ObjectiveError.BADPARAMS);
                return ImmutableSet.of();
            }
        }

        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 ImmutableSet.of();
    }

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

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

    @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");
    }

    protected 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");
    }


}
