/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.apache.karaf.shell.api.action.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.
 */
@Service
@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 doExecute() {
        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 ("IMMEDIATE".equals(liveTypeUC)) {
            return FlowEntry.FlowLiveType.IMMEDIATE;
        } else if ("SHORT".equals(liveTypeUC)) {
            return FlowEntry.FlowLiveType.SHORT;
        } else if ("MID".equals(liveTypeUC)) {
            return FlowEntry.FlowLiveType.MID;
        } else if ("LONG".equals(liveTypeUC)) {
            return FlowEntry.FlowLiveType.LONG;
        } else if ("UNKNOWN".equals(liveTypeUC)) {
            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 ("OUTPUT".equals(instTypeUC)) {
            return Instruction.Type.OUTPUT;
        } else if ("GROUP".equals(instTypeUC)) {
            return Instruction.Type.GROUP;
        } else if ("L0MODIFICATION".equals(instTypeUC)) {
            return Instruction.Type.L0MODIFICATION;
        } else if ("L2MODIFICATION".equals(instTypeUC)) {
            return Instruction.Type.L2MODIFICATION;
        } else if ("TABLE".equals(instTypeUC)) {
            return Instruction.Type.TABLE;
        } else if ("L3MODIFICATION".equals(instTypeUC)) {
            return Instruction.Type.L3MODIFICATION;
        } else if ("METADATA".equals(instTypeUC)) {
            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}");
    }
}
