/*
 * 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;
                            if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction ||
                                    l2i instanceof L2ModificationInstruction.ModEtherInstruction) {
                                return true;
                            }
                        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;
                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");
    }


}
