/*
 * 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.apache.karaf.shell.commands.Option;
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.device.DeviceService;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.StoredFlowEntry;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.statistic.FlowEntryWithLoad;
import org.onosproject.net.statistic.FlowStatisticService;
import org.onosproject.net.statistic.SummaryFlowEntryWithLoad;

import java.util.List;
import java.util.Map;

import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.PortNumber.portNumber;

/**
 * Fetches flow statistics with a flow type and instruction type.
 */
@Command(scope = "onos", name = "get-flow-stats",
        description = "Fetches flow stats for a connection point with given flow type and instruction type")
public class GetFlowStatisticsCommand extends AbstractShellCommand {
    @Argument(index = 0, name = "devicePort",
            description = "Device[/Port] connectPoint Description",
            required = true, multiValued = false)
    String devicePort = null;

    @Option(name = "-s", aliases = "--summary",
            description = "Show flow stats summary",
            required = false, multiValued = false)
    boolean showSummary = true; // default summary

    @Option(name = "-a", aliases = "--all",
            description = "Show flow stats all",
            required = false, multiValued = false)
    boolean showAll = false;

    @Option(name = "-t", aliases = "--topn",
            description = "Show flow stats topn entry",
            required = false, multiValued = false)
    String showTopn = null;

    @Option(name = "-f", aliases = "--flowType",
            description = "Flow live type, It includes IMMEDIATE, SHORT, MID, LONG, UNKNOWN"
                          + ", and is valid with -a or -t option only",
            required = false, multiValued = false)
    String flowLiveType = null;

    @Option(name = "-i", aliases = "--instructionType",
            description = "Flow instruction type, It includes DROP, OUTPUT, GROUP, L0MODIFICATION, L2MODIFICATION,"
                    + " TABLE, L3MODIFICATION, METADATA"
                    + ", and is valid with -a or -t option only",
            required = false, multiValued = false)
    String instructionType = null;

    @Override
    protected void execute() {
        DeviceService deviceService = get(DeviceService.class);
        FlowStatisticService flowStatsService = get(FlowStatisticService.class);

        String deviceUri = getDeviceId(devicePort);
        String portUri = getPortNumber(devicePort);

        DeviceId ingressDeviceId = deviceId(deviceUri);
        PortNumber ingressPortNumber;
        if (portUri.length() == 0) {
            ingressPortNumber = null;
        } else {
            ingressPortNumber = portNumber(portUri);
        }

        Device device = deviceService.getDevice(ingressDeviceId);
        if (device == null) {
            error("No such device %s", ingressDeviceId.uri());
            return;
        }

        if (ingressPortNumber != null) {
            Port port = deviceService.getPort(ingressDeviceId, ingressPortNumber);
            if (port == null) {
                error("No such port %s on device %s", portUri, ingressDeviceId.uri());
                return;
            }
        }

        if (flowLiveType != null) {
            flowLiveType = flowLiveType.toUpperCase();
        }
        if (instructionType != null) {
            instructionType = instructionType.toUpperCase();
        }

        // convert String to FlowLiveType and check validity
        FlowEntry.FlowLiveType inLiveType;
        if (flowLiveType == null) {
            inLiveType = null;
        } else {
            inLiveType = getFlowLiveType(flowLiveType);
            if (inLiveType == null) {
                error("Invalid flow live type [%s] error", flowLiveType);
                return;
            }
        }
        // convert String to InstructionType and check validity
        Instruction.Type inInstructionType;
        if (instructionType == null) {
            inInstructionType = null;
        } else {
            inInstructionType = getInstructionType(instructionType);
            if (inInstructionType == null) {
                error("Invalid instruction type [%s] error", instructionType);
                return;
            }
        }

        if (showTopn != null) {
            int topn = Integer.parseInt(showTopn);

            if (topn <= 0) {
                topn = 100; //default value
            } else if (topn > 1000) {
                topn = 1000; //max value
            }

            // print show topn head line with type
            print("deviceId=%s, show TOPN=%s flows, liveType=%s, instruction type=%s",
                    deviceUri,
                    Integer.toString(topn),
                    flowLiveType == null ? "ALL" : flowLiveType,
                    instructionType == null ? "ALL" : instructionType);
            if (ingressPortNumber == null) {
                Map<ConnectPoint, List<FlowEntryWithLoad>> typedFlowLoadMap =
                          flowStatsService.loadTopnByType(device, inLiveType, inInstructionType, topn);
                // print all ports topn flows load for a given device
                for (ConnectPoint cp : typedFlowLoadMap.keySet()) {
                    printPortFlowsLoad(cp, typedFlowLoadMap.get(cp));
                }
            } else {
                List<FlowEntryWithLoad> typedFlowLoad =
                        flowStatsService.loadTopnByType(device, ingressPortNumber, inLiveType, inInstructionType, topn);
                // print device/port topn flows load
                ConnectPoint cp = new ConnectPoint(ingressDeviceId, ingressPortNumber);
                printPortFlowsLoad(cp, typedFlowLoad);
            }
        } else if (showAll) { // is true?
            // print show all head line with type
            print("deviceId=%s, show ALL flows, liveType=%s, instruction type=%s",
                    deviceUri,
                    flowLiveType == null ? "ALL" : flowLiveType,
                    instructionType == null ? "ALL" : instructionType);
            if (ingressPortNumber == null) {
                Map<ConnectPoint, List<FlowEntryWithLoad>> typedFlowLoadMap =
                        flowStatsService.loadAllByType(device, inLiveType, inInstructionType);
                // print all ports all flows load for a given device
                for (ConnectPoint cp : typedFlowLoadMap.keySet()) {
                    printPortFlowsLoad(cp, typedFlowLoadMap.get(cp));
                }
            } else {
                List<FlowEntryWithLoad> typedFlowLoad =
                        flowStatsService.loadAllByType(device, ingressPortNumber, inLiveType, inInstructionType);
                // print device/port all flows load
                ConnectPoint cp = new ConnectPoint(ingressDeviceId, ingressPortNumber);
                printPortFlowsLoad(cp, typedFlowLoad);
            }
        } else { // if (showSummary == true) //always is true
            // print show summary head line
            print("deviceId=%s, show SUMMARY flows", deviceUri);
            if (ingressPortNumber == null) {
                Map<ConnectPoint, SummaryFlowEntryWithLoad> summaryFlowLoadMap =
                        flowStatsService.loadSummary(device);
                // print all ports flow load summary for a given device
                for (ConnectPoint cp : summaryFlowLoadMap.keySet()) {
                    printPortSummaryLoad(cp, summaryFlowLoadMap.get(cp));
                }
            } else {
                SummaryFlowEntryWithLoad summaryFlowLoad =
                        flowStatsService.loadSummary(device, ingressPortNumber);
                // print device/port flow load summary
                ConnectPoint cp = new ConnectPoint(ingressDeviceId, ingressPortNumber);
                printPortSummaryLoad(cp, summaryFlowLoad);
            }
        }
    }

    /**
     * Extracts the port number portion of the ConnectPoint.
     *
     * @param deviceString string representing the device/port
     * @return port number as a string, empty string if the port is not found
     */
    private String getPortNumber(String deviceString) {
        if (deviceString == null) {
            return "";
        }

        int slash = deviceString.indexOf('/');
        if (slash <= 0) {
            return ""; // return when no port number
        }
        return deviceString.substring(slash + 1, deviceString.length());
    }

    /**
     * Extracts the device ID portion of the ConnectPoint.
     *
     * @param deviceString string representing the device/port
     * @return device ID string
     */
    private String getDeviceId(String deviceString) {
        if (deviceString == null) {
            return "";
        }

        int slash = deviceString.indexOf('/');
        if (slash <= 0) {
            return deviceString; // return only included device ID
        }
        return deviceString.substring(0, slash);
    }

    /**
     * converts string of flow live type to FlowLiveType enum.
     *
     * @param liveType string representing the flow live type
     * @return FlowEntry.FlowLiveType
     */
    private FlowEntry.FlowLiveType getFlowLiveType(String liveType) {
        String liveTypeUC = liveType.toUpperCase();

        if (liveTypeUC.equals("IMMEDIATE")) {
            return FlowEntry.FlowLiveType.IMMEDIATE;
        } else if (liveTypeUC.equals("SHORT")) {
            return FlowEntry.FlowLiveType.SHORT;
        } else if (liveTypeUC.equals("MID")) {
            return FlowEntry.FlowLiveType.MID;
        } else if (liveTypeUC.equals("LONG")) {
            return FlowEntry.FlowLiveType.LONG;
        } else if (liveTypeUC.equals("UNKNOWN")) {
            return FlowEntry.FlowLiveType.UNKNOWN;
        } else {
            return null; // flow live type error
        }
    }

    /**
     * converts string of instruction type to Instruction type enum.
     *
     * @param instType string representing the instruction type
     * @return Instruction.Type
     */
    private Instruction.Type getInstructionType(String instType) {
        String instTypeUC = instType.toUpperCase();

        if (instTypeUC.equals("OUTPUT")) {
            return Instruction.Type.OUTPUT;
        } else if (instTypeUC.equals("GROUP")) {
            return Instruction.Type.GROUP;
        } else if (instTypeUC.equals("L0MODIFICATION")) {
            return Instruction.Type.L0MODIFICATION;
        } else if (instTypeUC.equals("L2MODIFICATION")) {
            return Instruction.Type.L2MODIFICATION;
        } else if (instTypeUC.equals("TABLE")) {
            return Instruction.Type.TABLE;
        } else if (instTypeUC.equals("L3MODIFICATION")) {
            return Instruction.Type.L3MODIFICATION;
        } else if (instTypeUC.equals("METADATA")) {
            return Instruction.Type.METADATA;
        } else {
             return null; // instruction type error
        }
    }

    private void printPortFlowsLoad(ConnectPoint cp, List<FlowEntryWithLoad> typedFlowLoad) {
       print("  deviceId/Port=%s/%s, %s flows", cp.elementId(), cp.port(), typedFlowLoad.size());
        for (FlowEntryWithLoad fel: typedFlowLoad) {
            StoredFlowEntry sfe =  fel.storedFlowEntry();
            print("    flowId=%s, state=%s, liveType=%s, life=%s -> %s",
                  Long.toHexString(sfe.id().value()),
                  sfe.state(),
                  sfe.liveType(),
                  sfe.life(),
                  fel.load().isValid() ? fel.load() : "Load{rate=0, NOT VALID}");
        }
    }

    private void printPortSummaryLoad(ConnectPoint cp, SummaryFlowEntryWithLoad summaryFlowLoad) {
        print("  deviceId/Port=%s/%s, Total=%s, Immediate=%s, Short=%s, Mid=%s, Long=%s, Unknown=%s",
                cp.elementId(),
                cp.port(),
                summaryFlowLoad.totalLoad().isValid() ? summaryFlowLoad.totalLoad() : "Load{rate=0, NOT VALID}",
                summaryFlowLoad.immediateLoad().isValid() ? summaryFlowLoad.immediateLoad() : "Load{rate=0, NOT VALID}",
                summaryFlowLoad.shortLoad().isValid() ? summaryFlowLoad.shortLoad() : "Load{rate=0, NOT VALID}",
                summaryFlowLoad.midLoad().isValid() ? summaryFlowLoad.midLoad() : "Load{rate=0, NOT VALID}",
                summaryFlowLoad.longLoad().isValid() ? summaryFlowLoad.longLoad() : "Load{rate=0, NOT VALID}",
                summaryFlowLoad.unknownLoad().isValid() ? summaryFlowLoad.unknownLoad() : "Load{rate=0, NOT VALID}");
    }
}
