/*
 * Copyright 2015 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.osgi.ServiceDirectory;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.behaviour.Pipeliner;
import org.onosproject.net.behaviour.PipelinerContext;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
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.FlowRuleService;
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.EthTypeCriterion;
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.Instructions.OutputInstruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.FlowObjectiveStore;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.store.serializers.KryoNamespaces;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import static org.onlab.util.Tools.delay;
import static org.slf4j.LoggerFactory.getLogger;

/**
 *  Simple 2-Table Pipeline for Software/NPU based routers. This pipeline
 *  does not forward IP traffic to next-hop groups. Instead it forwards traffic
 *  using OF FlowMod actions.
 */
public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipeliner {

    protected static final int FILTER_TABLE = 0;
    protected static final int FIB_TABLE = 1;

    private static final int DROP_PRIORITY = 0;
    private static final int DEFAULT_PRIORITY = 0x8000;
    private static final int HIGHEST_PRIORITY = 0xffff;

    private ServiceDirectory serviceDirectory;
    protected FlowRuleService flowRuleService;
    private CoreService coreService;
    private FlowObjectiveStore flowObjectiveStore;
    protected DeviceId deviceId;
    protected ApplicationId appId;
    private ApplicationId driverId;

    private KryoNamespace appKryo = new KryoNamespace.Builder()
        .register(DummyGroup.class)
        .register(KryoNamespaces.API)
        .register(byte[].class)
        .build();

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

    @Override
    public void init(DeviceId deviceId, PipelinerContext context) {
        this.serviceDirectory = context.directory();
        this.deviceId = deviceId;
        coreService = serviceDirectory.get(CoreService.class);
        flowRuleService = serviceDirectory.get(FlowRuleService.class);
        flowObjectiveStore = context.store();
        driverId = coreService.registerApplication(
                "org.onosproject.driver.SoftRouterPipeline");

        initializePipeline();
    }

    @Override
    public void filter(FilteringObjective filteringObjective) {
        if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
            processFilter(filteringObjective,
                          filteringObjective.op() == Objective.Operation.ADD,
                          filteringObjective.appId());
        } else {
            fail(filteringObjective, ObjectiveError.UNSUPPORTED);
        }
    }

    @Override
    public void forward(ForwardingObjective fwd) {
        Collection<FlowRule> rules;
        FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();

        rules = processForward(fwd);
        switch (fwd.op()) {
            case ADD:
                rules.stream()
                        .filter(Objects::nonNull)
                        .forEach(flowOpsBuilder::add);
                break;
            case REMOVE:
                rules.stream()
                        .filter(Objects::nonNull)
                        .forEach(flowOpsBuilder::remove);
                break;
            default:
                fail(fwd, ObjectiveError.UNKNOWN);
                log.warn("Unknown forwarding type {}", fwd.op());
        }


        flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
            @Override
            public void onSuccess(FlowRuleOperations ops) {
                pass(fwd);
            }

            @Override
            public void onError(FlowRuleOperations ops) {
                fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
            }
        }));

    }

    @Override
    public void next(NextObjective nextObjective) {
        switch (nextObjective.type()) {
        case SIMPLE:
            Collection<TrafficTreatment> treatments = nextObjective.next();
            if (treatments.size() != 1) {
                log.error("Next Objectives of type Simple should only have a "
                        + "single Traffic Treatment. Next Objective Id:{}", nextObjective.id());
               fail(nextObjective, ObjectiveError.BADPARAMS);
               return;
            }
            processSimpleNextObjective(nextObjective);
            break;
        case HASHED:
        case BROADCAST:
        case FAILOVER:
            fail(nextObjective, ObjectiveError.UNSUPPORTED);
            log.warn("Unsupported next objective type {}", nextObjective.type());
            break;
        default:
            fail(nextObjective, ObjectiveError.UNKNOWN);
            log.warn("Unknown next objective type {}", nextObjective.type());
        }
    }

    private void pass(Objective obj) {
        obj.context().ifPresent(context -> context.onSuccess(obj));
    }

    private void fail(Objective obj, ObjectiveError error) {
        obj.context().ifPresent(context -> context.onError(obj, error));
    }

    private void initializePipeline() {
        //Drop rules for both tables
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        FlowRuleOperations.Builder ops = FlowRuleOperations.builder();

        treatment.drop();

        FlowRule rule = DefaultFlowRule.builder()
                .forDevice(deviceId)
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(DROP_PRIORITY)
                .fromApp(driverId)
                .makePermanent()
                .forTable(FILTER_TABLE)
                .build();
        ops = ops.add(rule);

        rule = DefaultFlowRule.builder().forDevice(deviceId)
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(DROP_PRIORITY)
                .fromApp(driverId)
                .makePermanent()
                .forTable(FIB_TABLE)
                .build();
        ops = ops.add(rule);

        flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
            @Override
            public void onSuccess(FlowRuleOperations ops) {
                log.info("Provisioned drop rules in both tables");
            }

            @Override
            public void onError(FlowRuleOperations ops) {
                log.info("Failed to provision drop rules");
            }
        }));
    }

    private void processFilter(FilteringObjective filt, boolean install,
                               ApplicationId applicationId) {
        // This driver only processes filtering criteria defined with switch
        // ports as the key
        PortCriterion p;
        EthCriterion e = null;
        VlanIdCriterion v = null;

        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) {
                e = (EthCriterion) c;
            } else if (c.type() == Criterion.Type.VLAN_VID) {
                v = (VlanIdCriterion) c;
            } else {
                log.error("Unsupported filter {}", c);
                fail(filt, ObjectiveError.UNSUPPORTED);
                return;
            }
        }

        log.debug("adding Port/VLAN/MAC filtering rules in filter table: {}/{}/{}",
                  p.port(), v.vlanId(), e.mac());
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        selector.matchInPort(p.port());

        selector.matchEthDst(e.mac());
        selector.matchVlanId(v.vlanId());
        selector.matchEthType(Ethernet.TYPE_IPV4);
        if (!v.vlanId().equals(VlanId.NONE)) {
            treatment.popVlan();
        }
        treatment.transition(FIB_TABLE);
        FlowRule rule = DefaultFlowRule.builder()
                .forDevice(deviceId)
                .withSelector(selector.build())
                .withTreatment(treatment.build())
                .withPriority(DEFAULT_PRIORITY)
                .fromApp(applicationId)
                .makePermanent()
                .forTable(FILTER_TABLE).build();
        ops =  ops.add(rule);

        ops = install ? ops.add(rule) : ops.remove(rule);
        // apply filtering flow rules
        flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
            @Override
            public void onSuccess(FlowRuleOperations ops) {
                log.info("Applied filtering rules");
                pass(filt);
            }

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

    private Collection<FlowRule> processForward(ForwardingObjective fwd) {
        switch (fwd.flag()) {
        case SPECIFIC:
            return processSpecific(fwd);
        case VERSATILE:
            return processVersatile(fwd);
        default:
            fail(fwd, ObjectiveError.UNKNOWN);
            log.warn("Unknown forwarding flag {}", fwd.flag());
        }
        return Collections.emptySet();
    }

    /**
     * SoftRouter has a single versatile table - the filter table.
     * This table can be used to filter entries that reach the next table (FIB table).
     * It can also be used to punt packets to the controller and/or bypass
     * the FIB table to forward out of a port.
     *
     * @param fwd The forwarding objective of type versatile
     * @return  A collection of flow rules meant to be delivered to the flowrule
     *          subsystem. May return empty collection in case of failures.
     */
    private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
        log.debug("Received versatile fwd: to next:{}", fwd.nextId());
        Collection<FlowRule> flowrules = new ArrayList<>();
        if (fwd.nextId() == null && fwd.treatment() == null) {
            log.error("Forwarding objective {} from {} must contain "
                    + "nextId or Treatment", fwd.selector(), fwd.appId());
            return Collections.emptySet();
        }
        TrafficTreatment.Builder ttBuilder = DefaultTrafficTreatment.builder();
        if (fwd.treatment() != null) {
            fwd.treatment().immediate().forEach(ins -> ttBuilder.add(ins));
        }
        //convert nextId to flow actions
        if (fwd.nextId() != null) {
            // only acceptable value is output to port
            NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
            if (next == null) {
                log.error("next-id {} does not exist in store", fwd.nextId());
                return Collections.emptySet();
            }
            TrafficTreatment nt = appKryo.deserialize(next.data());
            if (nt == null)  {
                log.error("Error in deserializing next-id {}", fwd.nextId());
                return Collections.emptySet();
            }
            for (Instruction ins : nt.allInstructions()) {
                if (ins instanceof OutputInstruction) {
                    ttBuilder.add(ins);
                }
            }
        }

        FlowRule rule = DefaultFlowRule.builder()
                .withSelector(fwd.selector())
                .withTreatment(ttBuilder.build())
                .makePermanent()
                .forDevice(deviceId)
                .fromApp(fwd.appId())
                .withPriority(fwd.priority())
                .build();

        flowrules.add(rule);

        return flowrules;
    }

    /**
     * SoftRouter has a single specific table - the FIB Table. It emulates
     * LPM matching of dstIP by using higher priority flows for longer prefixes.
     * Flows are forwarded using flow-actions
     *
     * @param fwd The forwarding objective of type simple
     * @return A collection of flow rules meant to be delivered to the flowrule
     *         subsystem. Typically the returned collection has a single flowrule.
     *         May return empty collection in case of failures.
     *
     */
    private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
        log.debug("Processing specific forwarding objective to next:{}", fwd.nextId());
        TrafficSelector selector = fwd.selector();
        EthTypeCriterion ethType =
                (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
        // XXX currently supporting only the L3 unicast table
        if (ethType == null || ethType.ethType().toShort() != Ethernet.TYPE_IPV4) {
            fail(fwd, ObjectiveError.UNSUPPORTED);
            return Collections.emptySet();
        }

        IpPrefix ipPrefix = ((IPCriterion)
                selector.getCriterion(Criterion.Type.IPV4_DST)).ip();

        TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder()
                        .matchEthType(Ethernet.TYPE_IPV4);

        if (ipPrefix.prefixLength() != 0) {
            filteredSelector.matchIPDst(ipPrefix);
        }

        TrafficTreatment tt = null;
        if (fwd.nextId() != null) {
            NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
            if (next == null) {
                log.error("next-id {} does not exist in store", fwd.nextId());
                return Collections.emptySet();
            }
            tt = appKryo.deserialize(next.data());
            if (tt == null)  {
                log.error("Error in deserializing next-id {}", fwd.nextId());
                return Collections.emptySet();
            }
        }

        FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
                .fromApp(fwd.appId())
                .withPriority(fwd.priority())
                .forDevice(deviceId)
                .withSelector(filteredSelector.build());

        if (tt != null) {
            ruleBuilder.withTreatment(tt);
        }

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

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

    /**
     * Next Objectives are stored as dummy groups for retrieval later
     * when Forwarding Objectives reference the next objective id. At that point
     * the dummy group is fetched from the distributed store and the enclosed
     * treatment is applied as a flow rule action.
     *
     * @param nextObj the next objective of type simple
     */
    private void processSimpleNextObjective(NextObjective nextObj) {
        // Simple next objective has a single treatment (not a collection)
        log.debug("Received nextObj {}", nextObj.id());
        // delay processing to emulate group creation
        delay(50);
        TrafficTreatment treatment = nextObj.next().iterator().next();
        flowObjectiveStore.putNextGroup(nextObj.id(),
                                        new DummyGroup(treatment));
    }

    private class DummyGroup implements NextGroup {
        TrafficTreatment nextActions;

        public DummyGroup(TrafficTreatment next) {
            this.nextActions = next;
        }

        @Override
        public byte[] data() {
            return appKryo.serialize(nextActions);
        }

    }

    @Override
    public List<String> getNextMappings(NextGroup nextGroup) {
        // nextObjectives converted to flow-actions not groups
        return Collections.emptyList();
    }

}
