/*
 * 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.TypedStoredFlowEntry;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.statistic.FlowStatisticService;
import org.onosproject.net.statistic.SummaryFlowEntryWithLoad;
import org.onosproject.net.statistic.TypedFlowEntryWithLoad;

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",
            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
        TypedStoredFlowEntry.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, live type=%s, instruction type=%s",
                    deviceUri,
                    Integer.toString(topn),
                    flowLiveType == null ? "ALL" : flowLiveType,
                    instructionType == null ? "ALL" : instructionType);
            if (ingressPortNumber == null) {
                Map<ConnectPoint, List<TypedFlowEntryWithLoad>> 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<TypedFlowEntryWithLoad> 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, live type=%s, instruction type=%s",
                    deviceUri,
                    flowLiveType == null ? "ALL" : flowLiveType,
                    instructionType == null ? "ALL" : instructionType);
            if (ingressPortNumber == null) {
                Map<ConnectPoint, List<TypedFlowEntryWithLoad>> 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<TypedFlowEntryWithLoad> 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 FloeLiveType enum.
     *
     * @param liveType string representing the flow live type
     * @return TypedStoredFlowEntry.FlowLiveType
     */
    private TypedStoredFlowEntry.FlowLiveType getFlowLiveType(String liveType) {
        String liveTypeUC = liveType.toUpperCase();

        if (liveTypeUC.equals("IMMEDIATE")) {
            return TypedStoredFlowEntry.FlowLiveType.IMMEDIATE_FLOW;
        } else if (liveTypeUC.equals("SHORT")) {
            return TypedStoredFlowEntry.FlowLiveType.SHORT_FLOW;
        } else if (liveTypeUC.equals("MID")) {
            return TypedStoredFlowEntry.FlowLiveType.MID_FLOW;
        } else if (liveTypeUC.equals("LONG")) {
            return TypedStoredFlowEntry.FlowLiveType.LONG_FLOW;
        } else if (liveTypeUC.equals("UNKNOWN")) {
            return TypedStoredFlowEntry.FlowLiveType.UNKNOWN_FLOW;
        } 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<TypedFlowEntryWithLoad> typedFlowLoad) {
       print("  deviceId/Port=%s/%s, %s flows", cp.elementId(), cp.port(), typedFlowLoad.size());
        for (TypedFlowEntryWithLoad tfel: typedFlowLoad) {
            TypedStoredFlowEntry tfe =  tfel.typedStoredFlowEntry();
            print("    flowId=%s, state=%s, liveType=%s, life=%s -> %s",
                    Long.toHexString(tfe.id().value()),
                    tfe.state(),
                    tfe.flowLiveType(),
                    tfe.life(),
                    tfel.load().isValid() ? tfel.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}");
    }
}
