/*
 * 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.sfc.installer.impl;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import org.onlab.osgi.DefaultServiceDirectory;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.NshServiceIndex;
import org.onosproject.net.NshServicePathId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.host.HostService;
import org.onosproject.sfc.installer.FlowClassifierInstallerService;
import org.onosproject.vtnrsc.FiveTuple;
import org.onosproject.vtnrsc.FlowClassifier;
import org.onosproject.vtnrsc.FlowClassifierId;
import org.onosproject.vtnrsc.PortChain;
import org.onosproject.vtnrsc.PortPair;
import org.onosproject.vtnrsc.PortPairGroup;
import org.onosproject.vtnrsc.PortPairGroupId;
import org.onosproject.vtnrsc.PortPairId;
import org.onosproject.vtnrsc.VirtualPortId;
import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
import org.onosproject.vtnrsc.portpair.PortPairService;
import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
import org.onosproject.vtnrsc.service.VtnRscService;
import org.onosproject.vtnrsc.virtualport.VirtualPortService;
import org.slf4j.Logger;

/**
 * Provides flow classifier installer implementation.
 */
public class FlowClassifierInstallerImpl implements FlowClassifierInstallerService {
    private final Logger log = getLogger(getClass());

    protected VirtualPortService virtualPortService;
    protected VtnRscService vtnRscService;
    protected PortPairService portPairService;
    protected PortPairGroupService portPairGroupService;
    protected FlowClassifierService flowClassifierService;
    protected DriverService driverService;
    protected DeviceService deviceService;
    protected HostService hostService;
    protected FlowObjectiveService flowObjectiveService;
    protected ApplicationId appId;

    private static final String DRIVER_NAME = "onosfw";
    private static final String FLOW_CLASSIFIER_NOT_NULL = "Flow-Classifier cannot be null";
    private static final String FLOW_CLASSIFIER_ID_NOT_NULL = "Flow-Classifier-Id cannot be null";
    private static final String PORT_CHAIN_NOT_NULL = "Port-Chain cannot be null";
    private static final int NULL = 0;
    private static final int FLOW_CLASSIFIER_PRIORITY = 0x7fff;
    private static final short NSH_SI_ID = 0xff;

    /**
     * Default constructor.
     */
    public FlowClassifierInstallerImpl() {
    }

    /**
     * Explicit constructor.
     *
     * @param appId application id.
     */
    public FlowClassifierInstallerImpl(ApplicationId appId) {
        this.appId = checkNotNull(appId, "ApplicationId can not be null");
        ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
        this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
        this.driverService = serviceDirectory.get(DriverService.class);
        this.deviceService = serviceDirectory.get(DeviceService.class);
        this.hostService = serviceDirectory.get(HostService.class);
        this.virtualPortService = serviceDirectory.get(VirtualPortService.class);
        this.vtnRscService = serviceDirectory.get(VtnRscService.class);
        this.portPairService = serviceDirectory.get(PortPairService.class);
        this.portPairGroupService = serviceDirectory.get(PortPairGroupService.class);
        this.flowClassifierService = serviceDirectory.get(FlowClassifierService.class);
    }

    @Override
    public ConnectPoint installFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
        checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
        // Get the portPairGroup
        List<PortPairGroupId> llPortPairGroupIdList = portChain.portPairGroups();
        ListIterator<PortPairGroupId> portPairGroupIdListIterator = llPortPairGroupIdList.listIterator();
        PortPairGroupId portPairGroupId = portPairGroupIdListIterator.next();
        PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
        List<PortPairId> llPortPairIdList = portPairGroup.portPairs();

        // Get port pair
        ListIterator<PortPairId> portPairListIterator = llPortPairIdList.listIterator();
        PortPairId portPairId = portPairListIterator.next();
        PortPair portPair = portPairService.getPortPair(portPairId);

        return processFlowClassifier(portChain, portPair, nshSpiId, null, Objective.Operation.ADD);
    }

    @Override
    public ConnectPoint unInstallFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
        checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
        // Get the portPairGroup
        List<PortPairGroupId> llPortPairGroupIdList = portChain.portPairGroups();
        ListIterator<PortPairGroupId> portPairGroupIdListIterator = llPortPairGroupIdList.listIterator();
        PortPairGroupId portPairGroupId = portPairGroupIdListIterator.next();
        PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
        List<PortPairId> llPortPairIdList = portPairGroup.portPairs();

        // Get port pair
        ListIterator<PortPairId> portPairListIterator = llPortPairIdList.listIterator();
        PortPairId portPairId = portPairListIterator.next();
        PortPair portPair = portPairService.getPortPair(portPairId);

        return processFlowClassifier(portChain, portPair, nshSpiId, null, Objective.Operation.REMOVE);
    }

    @Override
    public ConnectPoint installLoadBalancedFlowClassifier(PortChain portChain, FiveTuple fiveTuple,
                                                          NshServicePathId nshSpiId) {
        checkNotNull(portChain, PORT_CHAIN_NOT_NULL);

        // Get the load balanced path
        List<PortPairId> portPairs = portChain.getLoadBalancePath(fiveTuple);

        // Get the first port pair
        ListIterator<PortPairId> portPairListIterator = portPairs.listIterator();
        PortPairId portPairId = portPairListIterator.next();
        PortPair portPair = portPairService.getPortPair(portPairId);

        return processFlowClassifier(portChain, portPair, nshSpiId, fiveTuple, Objective.Operation.ADD);
    }

    @Override
    public ConnectPoint unInstallLoadBalancedFlowClassifier(PortChain portChain, FiveTuple fiveTuple,
                                                            NshServicePathId nshSpiId) {
        checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
        // Get the load balanced path
        List<PortPairId> portPairs = portChain.getLoadBalancePath(fiveTuple);

        // Get the first port pair
        ListIterator<PortPairId> portPairListIterator = portPairs.listIterator();
        PortPairId portPairId = portPairListIterator.next();
        PortPair portPair = portPairService.getPortPair(portPairId);

        return processFlowClassifier(portChain, portPair, nshSpiId, fiveTuple, Objective.Operation.REMOVE);
    }

    public ConnectPoint processFlowClassifier(PortChain portChain, PortPair portPair, NshServicePathId nshSpiId,
                                              FiveTuple fiveTuple, Objective.Operation type) {

        DeviceId deviceIdfromPortPair = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.ingress()));
        MacAddress srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
        Host host = hostService.getHost(HostId.hostId(srcMacAddress));
        PortNumber port = host.location().port();

        DeviceId deviceId = deviceIdfromPortPair;

        // Vxlan tunnel port for NSH header(Vxlan + NSH).
        TpPort nshDstPort = TpPort.tpPort(6633);

        FlowClassifierInstallerService flowclassifierinstallerService;
        // get flow classifiers
        List<FlowClassifierId> llFlowClassifierList = portChain.flowClassifiers();
        ListIterator<FlowClassifierId> flowClassifierListIterator = llFlowClassifierList.listIterator();

        while (flowClassifierListIterator.hasNext()) {
            FlowClassifierId flowclassifierId = flowClassifierListIterator.next();
            FlowClassifier flowClassifier = flowClassifierService.getFlowClassifier(flowclassifierId);

            if ((flowClassifier.srcPort() != null) && (!flowClassifier.srcPort().portId().isEmpty())) {
                deviceId = vtnRscService.getSfToSffMaping(flowClassifier.srcPort());
            }

            // Build Traffic selector.
            TrafficSelector.Builder selector = packTrafficSelector(flowClassifier, fiveTuple);

            if (fiveTuple == null) {
                // Send the packet to controller
                TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
                treatment.setOutput(PortNumber.CONTROLLER);
                sendServiceFunctionClassifier(selector, treatment, deviceId, type);
            } else if (deviceId.equals(deviceIdfromPortPair)) {
                // classifier and source device are in the same OVS. So directly send packet to first port pair
                TrafficTreatment.Builder treatment = packTrafficTreatment(deviceId, port, nshDstPort,
                                                                          nshSpiId, flowClassifier, true);
                // Build forwarding objective and send to OVS.
                sendServiceFunctionClassifier(selector, treatment, deviceId, type);
            } else {
                // classifier and source device are not in the same OVS. Send packet on vlan Tunnel
                TrafficTreatment.Builder treatment = packTrafficTreatment(deviceId, port, nshDstPort,
                                                                          nshSpiId, flowClassifier, false);
                // Build forwarding objective and send to OVS.
                sendServiceFunctionClassifier(selector, treatment, deviceId, type);

                // At the other device get the packet from vlan and send to first port pair
                TrafficSelector.Builder selectorDst = DefaultTrafficSelector.builder();
                selectorDst.matchVlanId((VlanId.vlanId(Short.parseShort((vtnRscService
                        .getL3vni(flowClassifier.tenantId()).toString())))));
                TrafficTreatment.Builder treatmentDst = DefaultTrafficTreatment.builder();
                Host hostDst = hostService.getHost(HostId.hostId(srcMacAddress));
                treatmentDst.setOutput(hostDst.location().port());
                sendServiceFunctionClassifier(selectorDst, treatmentDst, deviceIdfromPortPair, type);
            }
        }
        return host.location();
    }

    /**
     * Pack Traffic selector.
     *
     * @param flowClassifier flow-classifier
     * @param fiveTuple five tuple info for the packet
     * @return traffic selector
     */
    public TrafficSelector.Builder packTrafficSelector(FlowClassifier flowClassifier, FiveTuple fiveTuple) {

        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();

        if ((flowClassifier.srcIpPrefix() != null) && (flowClassifier.srcIpPrefix().prefixLength() != 0)) {
            selector.matchIPSrc(flowClassifier.srcIpPrefix());
        } else if (fiveTuple != null && fiveTuple.ipSrc() != null) {
            selector.matchIPSrc(IpPrefix.valueOf(fiveTuple.ipSrc(), 24));
        }

        if ((flowClassifier.dstIpPrefix() != null) && (flowClassifier.dstIpPrefix().prefixLength() != 0)) {
            selector.matchIPDst(flowClassifier.dstIpPrefix());
        } else if (fiveTuple != null && fiveTuple.ipDst() != null) {
            selector.matchIPDst(IpPrefix.valueOf(fiveTuple.ipDst(), 24));
        }

        if ((flowClassifier.protocol() != null) && (!flowClassifier.protocol().isEmpty())) {
            if (flowClassifier.protocol().equalsIgnoreCase("TCP")) {
                selector.add(Criteria.matchIPProtocol(IPv4.PROTOCOL_TCP));
            } else if (flowClassifier.protocol().equalsIgnoreCase("UDP")) {
                selector.add(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP));
            }
        } else if (fiveTuple != null && fiveTuple.protocol() != 0) {
            selector.add(Criteria.matchIPProtocol(fiveTuple.protocol()));
        }

        if (((flowClassifier.etherType() != null) && (!flowClassifier.etherType().isEmpty()))
                && (flowClassifier.etherType().equals("IPv4") || flowClassifier.etherType().equals("IPv6"))) {
            if (flowClassifier.etherType().equals("IPv4")) {
                selector.matchEthType(Ethernet.TYPE_IPV4);
            } else {
                selector.matchEthType(Ethernet.TYPE_IPV6);
            }
        }

        if ((flowClassifier.srcPort() != null) && (!flowClassifier.srcPort().portId().isEmpty())) {
            VirtualPortId vPortId = VirtualPortId.portId(flowClassifier.srcPort().portId());
            MacAddress macAddress = virtualPortService.getPort(vPortId).macAddress();
            Host host = hostService.getHost(HostId.hostId(macAddress));
            selector.matchInPort(host.location().port());
        }

        // Take the port information from five tuple only when the protocol is TCP.
        if (fiveTuple != null && fiveTuple.protocol() == IPv4.PROTOCOL_TCP) {
            selector.matchTcpSrc(TpPort.tpPort((int) fiveTuple.portSrc().toLong()));
            selector.matchTcpDst(TpPort.tpPort((int) fiveTuple.portDst().toLong()));
        } else {
            // For udp packets take the port information from flow classifier
            List<TpPort> srcPortRange = new LinkedList<>();
            List<TpPort> dstPortRange = new LinkedList<>();
            if ((flowClassifier.minSrcPortRange() != 0) && flowClassifier.maxSrcPortRange() != 0
                    && flowClassifier.minDstPortRange() != 0 && flowClassifier.maxDstPortRange() != 0) {

                for (int port = flowClassifier.minSrcPortRange(); port <= flowClassifier.maxSrcPortRange(); port++) {
                    srcPortRange.add(TpPort.tpPort(port));
                }
                for (int port = flowClassifier.minDstPortRange(); port <= flowClassifier.maxDstPortRange(); port++) {
                    dstPortRange.add(TpPort.tpPort(port));
                }
            }

            for (TpPort inPort : srcPortRange) {
                selector.matchUdpSrc(inPort);
            }
            for (TpPort outPort : dstPortRange) {
                selector.matchUdpDst(outPort);
            }
        }
        return selector;
    }

    /**
     * Pack traffic treatment.
     *
     * @param deviceId device id
     * @param port port number
     * @param nshDstPort vxlan tunnel port for nsh header
     * @param nshSpi nsh spi
     * @param flowClassifier flow-classifier
     * @param isSameOvs whether the next service function is in same ovs
     * @return traffic treatment
     */
    public TrafficTreatment.Builder packTrafficTreatment(DeviceId deviceId, PortNumber port,
                                                         TpPort nshDstPort, NshServicePathId nshSpi,
                                                         FlowClassifier flowClassifier, boolean isSameOvs) {

        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();

        if (isSameOvs) {
            treatmentBuilder.setOutput(port);
        } else {
            treatmentBuilder.setVlanId((VlanId.vlanId(Short.parseShort((vtnRscService
                    .getL3vni(flowClassifier.tenantId()).toString())))));
            treatmentBuilder.setUdpDst(nshDstPort);
        }

        // Set NSH
        DriverHandler handler = driverService.createHandler(deviceId);
        ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
        ExtensionTreatment nspIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SPI.type());
        ExtensionTreatment nsiIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SI.type());

        treatmentBuilder.extension(nspIdTreatment, deviceId);
        treatmentBuilder.extension(nsiIdTreatment, deviceId);

        try {
            nspIdTreatment.setPropertyValue("nshSpi", nshSpi);
        } catch (Exception e) {
            log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
        }
        try {
            nsiIdTreatment.setPropertyValue("nshSi", NshServiceIndex.of(NSH_SI_ID));
        } catch (Exception e) {
            log.error("Failed to get extension instruction to set Nsh Si Id {}", deviceId);
        }

        return treatmentBuilder;
    }

    /**
     * Send service-function-forwarder to OVS.
     *
     * @param selector traffic selector
     * @param treatment traffic treatment
     * @param deviceId device id
     * @param type operation type
     */
    public void sendServiceFunctionClassifier(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment,
                                              DeviceId deviceId, Objective.Operation type) {
        log.info("Sending flow to service function classifier. Selector {}, Treatment {}",
                 selector.toString(), treatment.toString());
        ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
                .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.VERSATILE)
                .withPriority(FLOW_CLASSIFIER_PRIORITY);

        if (type.equals(Objective.Operation.ADD)) {
            log.debug("flowClassifierRules-->ADD");
            flowObjectiveService.forward(deviceId, objective.add());
        } else {
            log.debug("flowClassifierRules-->REMOVE");
            flowObjectiveService.forward(deviceId, objective.remove());
        }
    }
}
