/*
 * 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.Completion;
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)
    @Completion(ConnectPointCompleter.class)
    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}");
    }
}
