/*
 * Copyright 2014-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.cli.net;

import org.apache.karaf.shell.commands.Option;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onlab.util.Bandwidth;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.EncapsulationType;
import org.onosproject.net.PortNumber;
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.intent.Constraint;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.intent.constraint.EncapsulationConstraint;
import org.onosproject.net.intent.constraint.HashedPathSelectionConstraint;
import org.onosproject.net.intent.constraint.PartialFailureConstraint;

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

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onosproject.net.flow.DefaultTrafficTreatment.builder;

/**
 * Base class for command line operations for connectivity based intents.
 */
public abstract class ConnectivityIntentCommand extends AbstractShellCommand {

    // Selectors
    @Option(name = "-s", aliases = "--ethSrc", description = "Source MAC Address",
            required = false, multiValued = false)
    private String srcMacString = null;

    @Option(name = "-d", aliases = "--ethDst", description = "Destination MAC Address",
            required = false, multiValued = false)
    private String dstMacString = null;

    @Option(name = "-t", aliases = "--ethType", description = "Ethernet Type",
            required = false, multiValued = false)
    private String ethTypeString = null;

    @Option(name = "-v", aliases = "--vlan", description = "VLAN ID",
            required = false, multiValued = false)
    private String vlanString = null;

    @Option(name = "--ipProto", description = "IP Protocol",
            required = false, multiValued = false)
    private String ipProtoString = null;

    @Option(name = "--ipSrc", description = "Source IP Prefix",
            required = false, multiValued = false)
    private String srcIpString = null;

    @Option(name = "--ipDst", description = "Destination IP Prefix",
            required = false, multiValued = false)
    private String dstIpString = null;

    @Option(name = "--fLabel", description = "IPv6 Flow Label",
            required = false, multiValued = false)
    private String fLabelString = null;

    @Option(name = "--icmp6Type", description = "ICMPv6 Type",
            required = false, multiValued = false)
    private String icmp6TypeString = null;

    @Option(name = "--icmp6Code", description = "ICMPv6 Code",
            required = false, multiValued = false)
    private String icmp6CodeString = null;

    @Option(name = "--ndTarget", description = "IPv6 Neighbor Discovery Target Address",
            required = false, multiValued = false)
    private String ndTargetString = null;

    @Option(name = "--ndSLL", description = "IPv6 Neighbor Discovery Source Link-Layer",
            required = false, multiValued = false)
    private String ndSllString = null;

    @Option(name = "--ndTLL", description = "IPv6 Neighbor Discovery Target Link-Layer",
            required = false, multiValued = false)
    private String ndTllString = null;

    @Option(name = "--tcpSrc", description = "Source TCP Port",
            required = false, multiValued = false)
    private String srcTcpString = null;

    @Option(name = "--tcpDst", description = "Destination TCP Port",
            required = false, multiValued = false)
    private String dstTcpString = null;

    @Option(name = "--extHdr", description = "IPv6 Extension Header Pseudo-field",
            required = false, multiValued = true)
    private List<String> extHdrStringList = null;

    @Option(name = "-a", aliases = "--appId", description = "Application Id",
            required = false, multiValued = false)
    private String appId = null;

    @Option(name = "-k", aliases = "--key", description = "Intent Key",
            required = false, multiValued = false)
    private String intentKey = null;


    // Treatments
    @Option(name = "--setEthSrc", description = "Rewrite Source MAC Address",
            required = false, multiValued = false)
    private String setEthSrcString = null;

    @Option(name = "--setEthDst", description = "Rewrite Destination MAC Address",
            required = false, multiValued = false)
    private String setEthDstString = null;

    @Option(name = "--setIpSrc", description = "Rewrite Source IP Address",
            required = false, multiValued = false)
    private String setIpSrcString = null;

    @Option(name = "--setIpDst", description = "Rewrite Destination IP Address",
            required = false, multiValued = false)
    private String setIpDstString = null;

    @Option(name = "--setVlan", description = "Rewrite VLAN ID",
            required = false, multiValued = false)
    private String setVlan = null;

    @Option(name = "--popVlan", description = "Pop VLAN Tag",
            required = false, multiValued = false)
    private boolean popVlan = false;

    @Option(name = "--pushVlan", description = "Push VLAN ID",
            required = false, multiValued = false)
    private String pushVlan = null;

    @Option(name = "--setQueue", description = "Set Queue ID (for OpenFlow 1.0, " +
            "also the port has to be specified, i.e., <port>/<queue>",
            required = false, multiValued = false)
    private String setQueue = null;

    // Priorities
    @Option(name = "-p", aliases = "--priority", description = "Priority",
            required = false, multiValued = false)
    private int priority = Intent.DEFAULT_INTENT_PRIORITY;

    // Constraints
    @Option(name = "-b", aliases = "--bandwidth", description = "Bandwidth",
            required = false, multiValued = false)
    private String bandwidthString = null;

    @Option(name = "--partial", description = "Allow partial installation",
            required = false, multiValued = false)
    private boolean partial = false;

    @Option(name = "-e", aliases = "--encapsulation", description = "Encapsulation type",
            required = false, multiValued = false)
    private String encapsulationString = null;

    @Option(name = "--hashed", description = "Hashed path selection",
            required = false, multiValued = false)
    private boolean hashedPathSelection = false;


    /**
     * Constructs a traffic selector based on the command line arguments
     * presented to the command.
     * @return traffic selector
     */
    protected TrafficSelector buildTrafficSelector() {
        IpPrefix srcIpPrefix = null;
        IpPrefix dstIpPrefix = null;

        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();

        if (!isNullOrEmpty(srcIpString)) {
            srcIpPrefix = IpPrefix.valueOf(srcIpString);
            if (srcIpPrefix.isIp4()) {
                selectorBuilder.matchIPSrc(srcIpPrefix);
            } else {
                selectorBuilder.matchIPv6Src(srcIpPrefix);
            }
        }

        if (!isNullOrEmpty(dstIpString)) {
            dstIpPrefix = IpPrefix.valueOf(dstIpString);
            if (dstIpPrefix.isIp4()) {
                selectorBuilder.matchIPDst(dstIpPrefix);
            } else {
                selectorBuilder.matchIPv6Dst(dstIpPrefix);
            }
        }

        if ((srcIpPrefix != null) && (dstIpPrefix != null) &&
            (srcIpPrefix.version() != dstIpPrefix.version())) {
            // ERROR: IP src/dst version mismatch
            throw new IllegalArgumentException(
                        "IP source and destination version mismatch");
        }

        //
        // Set the default EthType based on the IP version if the matching
        // source or destination IP prefixes.
        //
        Short ethType = null;
        if ((srcIpPrefix != null) && srcIpPrefix.isIp6()) {
            ethType = EthType.IPV6.value();
        }
        if ((dstIpPrefix != null) && dstIpPrefix.isIp6()) {
            ethType = EthType.IPV6.value();
        }
        if (!isNullOrEmpty(ethTypeString)) {
            ethType = EthType.parseFromString(ethTypeString);
        }
        if (ethType != null) {
            selectorBuilder.matchEthType(ethType);
        }
        if (!isNullOrEmpty(vlanString)) {
            selectorBuilder.matchVlanId(VlanId.vlanId(Short.parseShort(vlanString)));
        }
        if (!isNullOrEmpty(srcMacString)) {
            selectorBuilder.matchEthSrc(MacAddress.valueOf(srcMacString));
        }

        if (!isNullOrEmpty(dstMacString)) {
            selectorBuilder.matchEthDst(MacAddress.valueOf(dstMacString));
        }

        if (!isNullOrEmpty(ipProtoString)) {
            short ipProtoShort = IpProtocol.parseFromString(ipProtoString);
            selectorBuilder.matchIPProtocol((byte) ipProtoShort);
        }

        if (!isNullOrEmpty(fLabelString)) {
            selectorBuilder.matchIPv6FlowLabel(Integer.parseInt(fLabelString));
        }

        if (!isNullOrEmpty(icmp6TypeString)) {
            byte icmp6Type = Icmp6Type.parseFromString(icmp6TypeString);
            selectorBuilder.matchIcmpv6Type(icmp6Type);
        }

        if (!isNullOrEmpty(icmp6CodeString)) {
            byte icmp6Code = Icmp6Code.parseFromString(icmp6CodeString);
            selectorBuilder.matchIcmpv6Code(icmp6Code);
        }

        if (!isNullOrEmpty(ndTargetString)) {
            selectorBuilder.matchIPv6NDTargetAddress(Ip6Address.valueOf(ndTargetString));
        }

        if (!isNullOrEmpty(ndSllString)) {
            selectorBuilder.matchIPv6NDSourceLinkLayerAddress(MacAddress.valueOf(ndSllString));
        }

        if (!isNullOrEmpty(ndTllString)) {
            selectorBuilder.matchIPv6NDTargetLinkLayerAddress(MacAddress.valueOf(ndTllString));
        }

        if (!isNullOrEmpty(srcTcpString)) {
            selectorBuilder.matchTcpSrc(TpPort.tpPort(Integer.parseInt(srcTcpString)));
        }

        if (!isNullOrEmpty(dstTcpString)) {
            selectorBuilder.matchTcpDst(TpPort.tpPort(Integer.parseInt(dstTcpString)));
        }

        if (extHdrStringList != null) {
            short extHdr = 0;
            for (String extHdrString : extHdrStringList) {
                extHdr = (short) (extHdr | ExtHeader.parseFromString(extHdrString));
            }
            selectorBuilder.matchIPv6ExthdrFlags(extHdr);
        }

        return selectorBuilder.build();
    }

    /**
     * Generates a traffic treatment for this intent based on command line
     * arguments presented to the command.
     *
     * @return traffic treatment
     */
    protected TrafficTreatment buildTrafficTreatment() {
        final TrafficTreatment.Builder treatmentBuilder = builder();
        boolean emptyTreatment = true;

        if (!isNullOrEmpty(setEthSrcString)) {
            treatmentBuilder.setEthSrc(MacAddress.valueOf(setEthSrcString));
            emptyTreatment = false;
        }

        if (!isNullOrEmpty(setEthDstString)) {
            treatmentBuilder.setEthDst(MacAddress.valueOf(setEthDstString));
            emptyTreatment = false;
        }

        if (!isNullOrEmpty(setIpSrcString)) {
            treatmentBuilder.setIpSrc(IpAddress.valueOf(setIpSrcString));
            emptyTreatment = false;
        }

        if (!isNullOrEmpty(setIpDstString)) {
            treatmentBuilder.setIpDst(IpAddress.valueOf(setIpDstString));
            emptyTreatment = false;
        }
        if (!isNullOrEmpty(setVlan)) {
            treatmentBuilder.setVlanId(VlanId.vlanId(Short.parseShort(setVlan)));
            emptyTreatment = false;
        }
        if (popVlan) {
            treatmentBuilder.popVlan();
            emptyTreatment = false;
        }
        if (!isNullOrEmpty(pushVlan)) {
            treatmentBuilder.pushVlan();
            treatmentBuilder.setVlanId(VlanId.vlanId(Short.parseShort(pushVlan)));
            emptyTreatment = false;
        }
        if (!isNullOrEmpty(setQueue)) {
            // OpenFlow 1.0 notation (for ENQUEUE): <port>/<queue>
            if (setQueue.contains("/")) {
                String[] queueConfig = setQueue.split("/");
                PortNumber port = PortNumber.portNumber(Long.parseLong(queueConfig[0]));
                long queueId = Long.parseLong(queueConfig[1]);
                treatmentBuilder.setQueue(queueId, port);
            } else {
                treatmentBuilder.setQueue(Long.parseLong(setQueue));
            }
            emptyTreatment = false;
        }

        if (emptyTreatment) {
            return DefaultTrafficTreatment.emptyTreatment();
        } else {
            return treatmentBuilder.build();
        }
    }

    /**
     * Builds the constraint list for this command based on the command line
     * parameters.
     *
     * @return List of constraint objects describing the constraints requested
     */
    protected List<Constraint> buildConstraints() {
        final List<Constraint> constraints = new LinkedList<>();

        // Check for a bandwidth specification
        if (!isNullOrEmpty(bandwidthString)) {
            Bandwidth bandwidth;
            try {
                bandwidth = Bandwidth.bps(Long.parseLong(bandwidthString));
            // when the string can't be parsed as long, then try to parse as double
            } catch (NumberFormatException e) {
                bandwidth = Bandwidth.bps(Double.parseDouble(bandwidthString));
            }
            constraints.add(new BandwidthConstraint(bandwidth));
        }

        // Check for partial failure specification
        if (partial) {
            constraints.add(new PartialFailureConstraint());
        }

        // Check for encapsulation specification
        if (!isNullOrEmpty(encapsulationString)) {
            final EncapsulationType encapType = EncapsulationType.valueOf(encapsulationString);
            constraints.add(new EncapsulationConstraint(encapType));
        }

        // Check for hashed path selection
        if (hashedPathSelection) {
            constraints.add(new HashedPathSelectionConstraint());
        }
        return constraints;
    }

    @Override
    protected ApplicationId appId() {
        ApplicationId appIdForIntent;
        if (appId == null) {
            appIdForIntent = super.appId();
        } else {
            CoreService service = get(CoreService.class);
            appIdForIntent = service.getAppId(appId);
        }
        return appIdForIntent;
    }

    /**
     * Creates a key for an intent based on command line arguments.  If a key
     * has been specified, it is returned.  If no key is specified, null
     * is returned.
     *
     * @return intent key if specified, null otherwise
     */
    protected Key key() {
        Key key = null;
        ApplicationId appIdForIntent;

        if (intentKey != null) {
            key = Key.of(intentKey, appId());
        }
        return key;
    }

    /**
     * Gets the priority to use for the intent.
     *
     * @return priority
     */
    protected int priority() {
        return priority;
    }
}
