/*
 * Copyright 2016-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.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onlab.packet.VlanId;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.VlanQuery;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;

/**
 * Command to show the list of unused vlan-ids.
 */
@Command(scope = "onos", name = "port-query-vlans",
        description = "Lists all unused VLAN-IDs on port")
public class PortQueryVlansCommand extends AbstractShellCommand {

    private static final String AVAIL_VLANS = "VLAN-ID: %s";
    private static final String VLAN_NOT_AVAILABLE = "No unused VLAN-ID";
    private static final String FMT = "port=%s, state=%s, type=%s, speed=%s%s";
    private static final String NO_SUPPORT = "Device not supporting VLAN-ID retrieval";
    private static final String FAILURE = "Failed to retrieve VLAN information: ";

    @Argument(index = 0, name = "port",
            description = "Port Description",
            required = true, multiValued = true)
    private String[] ports;


    @Override
    protected void execute() {
        DeviceService service = get(DeviceService.class);
        for (String portStr : ports) {
            ConnectPoint connectPoint = ConnectPoint.deviceConnectPoint(portStr);
            Port port = service.getPort(connectPoint.deviceId(), connectPoint.port());
            printPort(port);
            printVlans(port);
        }
    }

    private void printPort(Port port) {
        String portName = portName(port.number());
        Object portIsEnabled = port.isEnabled() ? "enabled" : "disabled";
        String portType = port.type().toString().toLowerCase();
        String annotations = annotations(port.annotations());
        print(FMT, portName, portIsEnabled, portType, port.portSpeed(), annotations);
    }

    private String portName(PortNumber port) {
        return port.equals(PortNumber.LOCAL) ? "local" : port.toString();
    }

    private void printVlans(Port port) {
        DeviceService deviceService = get(DeviceService.class);
        DriverService driverService = get(DriverService.class);

        DeviceId deviceId = (DeviceId) port.element().id();
        Device device = deviceService.getDevice(deviceId);

        if (!device.is(VlanQuery.class)) {
            // The relevant behavior is not supported by the device.
            print(NO_SUPPORT);
            return;
        }

        DriverHandler h = driverService.createHandler(deviceId);
        VlanQuery vlanQuery = h.behaviour(VlanQuery.class);

        try {
            Set<VlanId> vlanIds = vlanQuery.queryVlanIds(port.number());

            if (vlanIds.isEmpty()) {
                print(VLAN_NOT_AVAILABLE);
            } else {
                print(AVAIL_VLANS, getRanges(vlanIds).toString());
            }
        } catch (Exception e) {
            print(FAILURE + e.getMessage());
        }
    }

    private static ArrayList getRanges(Set<VlanId> vlans) {
        short i = 0;
        short[] vlanArray = new short[vlans.size()];
        for (VlanId vlanId : vlans) {
            vlanArray[i++] = vlanId.toShort();
        }
        Arrays.sort(vlanArray);

        ArrayList ranges = new ArrayList();
        short rStart = 0;
        short rEnd = 0;

        for (i = 2; i < vlanArray.length; i++) {
            if (vlanArray[i] == vlanArray[i - 1] + 1 &&
                    vlanArray[i] == vlanArray[i - 2] + 2) {
                // Three consecutive VLAN-IDs found, so range exists.
                if (rEnd == vlanArray[i - 1]) {
                    // Range already exists, so step the end.
                    rEnd = vlanArray[i];
                } else {
                    // Setup a new range.
                    rStart = vlanArray[i - 2];
                    rEnd = vlanArray[i];
                }
            } else {
                // Not in a range.
                if (rEnd == vlanArray[i - 1]) {
                    // Previous range is discontinued and is stored.
                    ranges.add(rStart + "-" + rEnd);
                } else {
                    // No previous range.
                    if (vlanArray[i] != vlanArray[i - 1] + 1) {
                        // Current VLAN-ID is not 2nd consecutive.
                        if (vlanArray[i - 1] == vlanArray[i - 2] + 1) {
                            // The 2 previous VLAN-IDs were consequetive, so 2nd
                            // last is stored separately.
                            ranges.add(vlanArray[i - 2]);
                        }
                        // Previous is stored, when current is not consequetive.
                        ranges.add(vlanArray[i - 1]);
                    }
                }
            }
        }
        if (rEnd == vlanArray[vlanArray.length - 1]) {
            // Array finished with a range.
            ranges.add(rStart + "-" + rEnd);
        } else {
            if (vlanArray[vlanArray.length - 1] == vlanArray[vlanArray.length - 2] + 1) {
                // Previous is stored, when current is consequetive.
                ranges.add(vlanArray[vlanArray.length - 2]);
            }
            // Last item is stored
            ranges.add(vlanArray[vlanArray.length - 1]);
        }
        return ranges;
    }
}
