/*
 * Copyright 2015-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 com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Streams;
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.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.LinkKey;
import org.onosproject.net.Port;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.PortStatistics;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.ObjectiveTrackerService;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.intent.WorkPartitionService;
import org.onosproject.net.statistic.FlowStatisticService;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;

@Command(scope = "onos", name = "intents-diagnosis",
        description = "Diagnosis intents")
public class IntentsDiagnosisCommand extends AbstractShellCommand {

    @Argument(index = 0, name = "key",
            description = "Intent key",
            required = false, multiValued = false)
    String key = null;

    @Option(name = "-d", aliases = "--details", description = "printing intent details",
            required = false, multiValued = false)
    private boolean dump = false;

    @Option(name = "-l", aliases = "--link", description = "printing local intentsByLink",
            required = false, multiValued = false)
    private boolean dumpIntentByLink = false;

    private static final int MAX_INTENT_PATH = 100;
    private static final String FIELD_INTENTS_BY_LINK = "intentsByLink";

    @Override
    protected void execute() {

        print("intents-diagnosis");
        ServiceRefs svcRefs = buildServiceRefs();
        if (svcRefs == null) {
            return;
        }
        try {
            for (Intent intent : svcRefs.intentsService().getIntents()) {
                if (key != null && !intent.key().toString().equals(key)) {
                    continue;
                }
                print("");
                printIntentHdr(intent, svcRefs);
                if (intent instanceof PointToPointIntent) {
                    diagnosisP2Pintent((PointToPointIntent) intent, svcRefs);
                } else {
                    // TODO : it needs to implement other types of intent
                    print(" It doesn't support %s intent.", intent.getClass().getSimpleName());
                }
            }
            if (dumpIntentByLink) {
                dumpIntentsByLink(svcRefs);
            }
        } catch (Exception e) {
            print("error: " + e);
        }

    }

    private void printIntentHdr(Intent intent, ServiceRefs svcRefs) {
        print("* intent key: %s", intent.key());
        print(" - state: %s", svcRefs.intentsService().getIntentState(intent.key()));
        dump(" - leader: %s %s", svcRefs.getWorkPartitionService().getLeader(intent.key(), Key::hash),
                svcRefs.workPartitionService.isMine(intent.key(), Key::hash) ? "(Mine)" : "");
    }

    private void dumpIntentsByLink(ServiceRefs svcRefs) throws Exception {
        Set<Map.Entry<LinkKey, Key>> intentsByLink = getIntentsByLinkSet(svcRefs);

        print("* intentsbylink:");
        for (Map.Entry<LinkKey, Key> entry : intentsByLink) {
            print(" - %s, Intents: %s ", entry.getKey(), entry.getValue());
        }
    }

    private Set<Map.Entry<LinkKey, Key>> getIntentsByLinkSet(ServiceRefs svcRefs) throws Exception {

        ObjectiveTrackerService objTracker = svcRefs.getObjectiveTrackerService();

        // Utilizing reflection instead of adding new interface for getting intentsByLink
        Field f = objTracker.getClass().getDeclaredField(FIELD_INTENTS_BY_LINK);
        f.setAccessible(true);
        SetMultimap<LinkKey, Key> intentsByLink = (SetMultimap<LinkKey, Key>) f.get(objTracker);

        return ImmutableSet.copyOf(intentsByLink.entries());
    }

    private void diagnosisP2Pintent(PointToPointIntent intent, ServiceRefs svcRefs) throws Exception {

        List<Intent> installableIntents = svcRefs.intentsService().getInstallableIntents(intent.key());

        if (installableIntents.size() == 0) {
            error("NO INSTALLABLE INTENTS");
            return;
        }

        Set<String> notSupport = new HashSet<>();
        for (Intent installable: installableIntents) {
            if (installable instanceof FlowRuleIntent) {
                checkP2PFlowRuleIntent(intent, (FlowRuleIntent) installable, svcRefs);
            } else {
                // TODO : it needs to implement other types of installables
                notSupport.add(installable.getClass().getSimpleName());
            }
        }

        if (notSupport.size() > 0) {
            print(" It doesn't support %s.", notSupport);
        }
    }

    private void checkP2PFlowRuleIntent(PointToPointIntent intent, FlowRuleIntent installable, ServiceRefs svcRefs)
            throws Exception {

        final Map<DeviceId, DeviceOnIntent> devs = createDevicesOnP2PIntent(intent, installable);

        boolean errorOccurred = false;
        // checking the number of links & CPs in P2P intent
        for (DeviceOnIntent dev: devs.values()) {
            if (dev.getIngressLinks().size() > 1) {
                error("MULTIPLE NUMBER OF INGRESS LINKs on " + dev.deviceId()
                        + ": " + dev.getIngressLinks());
                errorOccurred = true;
            }
            if (dev.getIngressCps().size() > 1) {
                error("MULTIPLE NUMBER OF INGRESS CONNECT POINTs on " + dev.deviceId()
                        + ": " + dev.getIngressCps());
                errorOccurred = true;
            }
            if (dev.getEgressLinks().size() > 1) {
                error("MULTIPLE NUMBER OF EGRESS LINKs: on " + dev.deviceId()
                        + ": " + dev.getEgressLinks());
                errorOccurred = true;
            }
            if (dev.getEgressCps().size() > 1) {
                error("MULTIPLE NUMBER OF EGRESS CONNECT POINTs: on " + dev.deviceId()
                        + ": " + dev.getEgressCps());
                errorOccurred = true;
            }
        }

        ConnectPoint startCp = intent.filteredIngressPoint().connectPoint();
        DeviceOnIntent startDev = devs.get(startCp.deviceId());
        if (startDev == null) {
            error("STARTING CONNECT POINT DEVICE: " + startCp.deviceId() + " is not on intent");
            errorOccurred = true;
        }

        ConnectPoint endCp = intent.filteredEgressPoint().connectPoint();
        DeviceOnIntent endDev = devs.get(endCp.deviceId());
        if (endDev == null) {
            error("END CONNECT POINT DEVICE: " + endCp.deviceId() + " is not on intent");
            errorOccurred = true;
        }

        if (!errorOccurred) {
            // Per device checking with path-order
            DeviceOnIntent dev = startDev;
            int i = 0;
            for (; i < MAX_INTENT_PATH; i++) {
                perDeviceChecking(dev, svcRefs);

                // P2P intent has only 1 egress CP
                ConnectPoint egressCp = dev.getEgressCps().stream().findFirst().orElse(null);
                if (egressCp != null && Objects.equals(endCp, egressCp)) {
                    break;
                }

                // P2P intent has only 1 egress link
                Link egressLink = dev.getEgressLinks().stream().findFirst().orElse(null);
                if (egressLink == null) {
                    error("INVALID EGRESS LINK & CONNECT POINT for: " + dev);
                    errorOccurred = true;
                    break;
                }
                if (Objects.equals(egressLink.dst(), endCp)) {
                    break;
                }

                // P2P intent only 1 ingress link
                dev = devs.values().stream()
                        .filter(nextDev -> Objects.equals(
                            egressLink, nextDev.getIngressLinks().stream().findFirst().orElse(null)))
                        .findAny().orElse(null);
                if (dev == null) {
                    error("FAILED TO FIND NEXT DEV for: " + dev + ", LINK: " + egressLink);
                    errorOccurred = true;
                    break;
                }
            }
            if (i == MAX_INTENT_PATH) {
                error("MAX INTENT PATH WAS EXCEEDED");
                errorOccurred = true;
            }
        }

        if (errorOccurred) {
            // Installable checking
            dump("");
            dump("ERROR OCCURRED. DO PER FLOW CHECKING");
            perFlowRuleChecking(installable, svcRefs);
        }

        if (svcRefs.workPartitionService.isMine(intent.key(), Key::hash)) {
            checkIntentsByLink(installable, svcRefs);
        }
    }

    private void checkIntentsByLink(FlowRuleIntent installable, ServiceRefs svcRefs) throws Exception {

        Set<Map.Entry<LinkKey, Key>> intentsByLink = getIntentsByLinkSet(svcRefs);

        installable.resources().forEach(
                rsrc -> {
                    if (rsrc instanceof Link) {
                        Link link = (Link) rsrc;
                        LinkKey linkKey = LinkKey.linkKey(link);
                        intentsByLink.stream()
                                .filter(entry -> Objects.equals(entry.getKey(), linkKey)
                                        && Objects.equals(entry.getValue(), installable.key()))
                                .findAny()
                                .orElseGet(() -> {
                                    error("FAILED TO FIND LINK(" + link + ") for intents: " + installable.key());
                                    return null;
                                });
                    }
                }
        );
    }

    // TODO: It needs to consider FLowObjectiveIntent case
    private void perDeviceChecking(DeviceOnIntent devOnIntent, ServiceRefs svcRefs) {

        Collection<PortStatistics> portStats =
                svcRefs.deviceService().getPortStatistics(devOnIntent.deviceId());
        Collection<PortStatistics> portDeltaStats =
                svcRefs.deviceService().getPortDeltaStatistics(devOnIntent.deviceId());

        dump("");
        dump(" ------------------------------------------------------------------------------------------");

        Device device = svcRefs.deviceService.getDevice(devOnIntent.deviceId());
        if (device == null) {
            error("INVALID DEVICE for " + devOnIntent.deviceId());
            return;
        }

        dump(" %s", getDeviceString(device));
        dump("  %s", device.annotations());

        devOnIntent.getIngressCps().stream()
                .forEach(cp -> dumpCpStatistics(cp, portStats, portDeltaStats, "INGRESS", svcRefs));

        Stream<FlowEntry> flowEntries = Streams.stream(svcRefs.flowService.getFlowEntries(devOnIntent.deviceId()));

        devOnIntent.getFlowRules().stream()
                .forEach(
                        intentFlowRule -> {
                            FlowEntry matchedEntry = flowEntries
                                    .filter(entry -> Objects.equals(intentFlowRule.id(), entry.id()))
                                    .findFirst().orElse(null);

                            if (matchedEntry == null) {
                                error("FAILED TO FIND FLOW ENTRY: for " + intentFlowRule);
                                return;
                            }

                            if (Objects.equals(intentFlowRule.selector(), matchedEntry.selector()) &&
                                    Objects.equals(intentFlowRule.treatment(), matchedEntry.treatment())) {
                                dumpFlowEntry(matchedEntry, "FLOW ENTRY");
                                return;
                            }

                            error("INSTALLABLE-FLOW ENTRY mismatch");
                            dumpFlowRule(intentFlowRule, "INSTALLABLE");
                            dumpFlowEntry(matchedEntry, "FLOW ENTRY");
                        }
                );

        devOnIntent.getEgressCps().stream()
                .forEach(
                        cp -> dumpCpStatistics(cp, portStats, portDeltaStats, "EGRESS", svcRefs)
                );
    }

    // TODO: It needs to consider FLowObjectiveIntent case
    private void perFlowRuleChecking(FlowRuleIntent installable, ServiceRefs svcRefs) {

        installable.flowRules().forEach(
                flowrule -> {
                    DeviceId devId = flowrule.deviceId();
                    if (devId == null) {
                        error("INVALID DEVICE ID for " + flowrule);
                        return;
                    }

                    Device dev = svcRefs.deviceService.getDevice(devId);
                    if (dev == null) {
                        error("INVALID DEVICE for " + flowrule);
                        return;
                    }

                    dump("");
                    dump(
                    " ------------------------------------------------------------------------------------------");
                    dump(" %s", getDeviceString(dev));
                    dump("  %s", dev.annotations());

                    svcRefs.flowService().getFlowEntries(devId)
                            .forEach(
                                    entry -> {
                                        dumpFlowRule(flowrule, "INSTALLABLE");
                                        dumpFlowEntry(entry, "FLOW ENTRY");

                                        if (!flowrule.selector().equals(entry.selector())) {
                                            return;
                                        }
                                        if (flowrule.id().equals(entry.id()) &&
                                                flowrule.treatment().equals(entry.treatment())) {
                                            dumpFlowEntry(entry, "FLOW ENTRY");
                                            return;
                                        }
                                        error("INSTALLABLE-FLOW ENTRY mismatch");
                                    }
                            );
                }
        );
    }

    private Map<DeviceId, DeviceOnIntent> createDevicesOnP2PIntent(
            PointToPointIntent intent, FlowRuleIntent flowRuleIntent) {

        final Map<DeviceId, DeviceOnIntent> devMap = new HashMap<>();

        flowRuleIntent.resources().forEach(
                rsrc -> {
                    if (rsrc instanceof Link) {
                        Link link = (Link) rsrc;
                        ConnectPoint srcCp = link.src();
                        ConnectPoint dstCp = link.dst();
                        try {
                            DeviceOnIntent dev = devMap.computeIfAbsent(srcCp.deviceId(), DeviceOnIntent::new);
                            if (dev != null) {
                                dev.addEgressLink(link);
                            }
                            dev = devMap.computeIfAbsent(dstCp.deviceId(), DeviceOnIntent::new);
                            if (dev != null) {
                                dev.addIngressLink(link);
                            }
                        } catch (IllegalStateException e) {
                            print("error: " + e);
                        }
                    }
                }
        );

        ConnectPoint startCp = intent.filteredIngressPoint().connectPoint();
        DeviceOnIntent startDev = devMap.computeIfAbsent(startCp.deviceId(), DeviceOnIntent::new);
        if (!startDev.hasIngressCp(startCp)) {
            startDev.addIngressCp(startCp);
        }

        ConnectPoint endCp = intent.filteredEgressPoint().connectPoint();
        DeviceOnIntent endDev = devMap.computeIfAbsent(endCp.deviceId(), DeviceOnIntent::new);
        if (!endDev.hasEgressCp(endCp)) {
            endDev.addEgessCp(endCp);
        }

        flowRuleIntent.flowRules().forEach(
                flowRule -> {
                    DeviceId devId = flowRule.deviceId();
                    if (devId == null) {
                        error("INVALID DEVICE ID for " + flowRule);
                        return;
                    }
                    DeviceOnIntent dev = devMap.get(devId);
                    if (dev == null) {
                        error("DEVICE(" + devId + ") IS NOT ON INTENTS LINKS");
                        return;
                    }

                    dev.addFlowRule(flowRule);
                }
        );

        return devMap;
    }

    private String getDeviceString(Device dev) {

        StringBuilder buf = new StringBuilder();
        if (dev != null) {
            buf.append(String.format("Device: %s, ", dev.id()));
            buf.append(String.format("%s, ", dev.type()));
            buf.append(String.format("%s, ", dev.manufacturer()));
            buf.append(String.format("%s, ", dev.hwVersion()));
            buf.append(String.format("%s, ", dev.swVersion()));
            if (dev instanceof DefaultDevice) {
                DefaultDevice dfltDev = (DefaultDevice) dev;
                if (dfltDev.driver() != null) {
                    buf.append(String.format("%s, ", dfltDev.driver().name()));
                }
                String channelId = dfltDev.annotations().value("channelId");
                if (channelId != null) {
                    buf.append(String.format("%s, ", channelId));
                }
            }
        }

        return buf.toString();
    }

    private void dumpFlowRule(FlowRule rule, String hdr) {
        dump("  " + hdr + ":");
        dump("   - id=%s, priority=%d", rule.id(), rule.priority());
        dump("   - %s", rule.selector());
        dump("   - %s", rule.treatment());
    }

    private void dumpFlowEntry(FlowEntry entry, String hdr) {
        dumpFlowRule(entry, hdr);
        dump("   - packets=%d", entry.packets());
    }


    private void dumpCpStatistics(ConnectPoint cp, Collection<PortStatistics> devPortStats,
                                  Collection<PortStatistics> devPortDeltaStats, String direction, ServiceRefs svcs) {
        if (cp == null) {
            return;
        }

        dump("  %s:", direction);

        if (cp.port().isLogical()) {
            dump("   - logical: device: %s, port: %s", cp.deviceId(), cp.port());
            return;
        }

        Port port =  svcs.deviceService.getPort(cp.deviceId(), cp.port());
        if (port == null) {
            return;
        }

        try {
            devPortStats.stream()
                    .filter(stat -> stat.portNumber().equals(cp.port()))
                    .forEach(stat -> dump("   - stat   : %s:", getPortStatStr(stat, port)));
        } catch (IllegalStateException e) {
            error("error: " + e);
            return;
        }

        try {
            devPortDeltaStats.stream()
                    .filter(stat -> stat.portNumber().equals(cp.port()))
                    .forEach(stat -> dump("   - delta  : %s:", getPortStatStr(stat, port)));
        } catch (IllegalStateException e) {
            error("error: " + e);
        }
    }

    private void dump(String format, Object ... args) {
        if (dump) {
            print(format, args);
        }
    }

    private String getPortStatStr(PortStatistics stat, Port port) {

        final String portName = port.annotations().value(AnnotationKeys.PORT_NAME);

        return String.format("port: %s(%s), ", stat.portNumber(), portName) +
                String.format("enabled: %b, ", port.isEnabled()) +
                String.format("pktRx: %d, ", stat.packetsReceived()) +
                String.format("pktTx: %d, ", stat.packetsSent()) +
                String.format("pktRxErr: %d, ", stat.packetsRxErrors()) +
                String.format("pktTxErr: %d, ", stat.packetsTxErrors()) +
                String.format("pktRxDrp: %d, ", stat.packetsRxDropped()) +
                String.format("pktTxDrp: %d", stat.packetsTxDropped());
    }

    private static class DeviceOnIntent {

        private final DeviceId devId;

        private Collection<Link> ingressLinks = new ArrayList<>();

        private Collection<Link> egressLinks = new ArrayList<>();

        private Collection<ConnectPoint> ingressCps = new ArrayList<>();

        private Collection<ConnectPoint> egressCps = new ArrayList<>();

        private Collection<FlowRule> flowRules = new ArrayList<>();

        public DeviceOnIntent(DeviceId devId) {
            this.devId = devId;
        }

        public DeviceId deviceId() {
            return devId;
        }

        public Collection<Link> getIngressLinks() {
            return ingressLinks;
        }

        public Collection<Link> getEgressLinks() {
            return egressLinks;
        }

        public void addIngressLink(Link link) {
            ingressLinks.add(link);
            addIngressCp(link.dst());
        }

        public void addEgressLink(Link link) {
            egressLinks.add(link);
            addEgessCp(link.src());
        }

        public void addIngressCp(ConnectPoint cp) {
            ingressCps.add(cp);
        }

        public void addEgessCp(ConnectPoint cp) {
            egressCps.add(cp);
        }

        public boolean hasIngressCp(final ConnectPoint cp) {
            return ingressCps.stream().anyMatch(icp -> Objects.equals(icp, cp));
        }

        public boolean hasEgressCp(ConnectPoint cp) {
            return egressCps.stream().anyMatch(ecp -> Objects.equals(ecp, cp));
        }

        public Collection<ConnectPoint> getIngressCps() {
            return ingressCps;
        }

        public Collection<ConnectPoint> getEgressCps() {
            return egressCps;
        }

        public Collection<FlowRule> getFlowRules() {
            return flowRules;
        }

        public void addFlowRule(FlowRule flowRule) {
            flowRules.add(flowRule);
        }

        public String toString() {
            return MoreObjects.toStringHelper(getClass())
                    .omitNullValues()
                    .add("devId", devId)
                    .add("ingressLinks", ingressLinks)
                    .add("egressLinks", egressLinks)
                    .add("flowRules", flowRules)
                    .toString();
        }
    }


    private ServiceRefs buildServiceRefs() {
        IntentService intentsService = get(IntentService.class);
        if (intentsService == null) {
            return null;
        }
        DeviceService deviceService = get(DeviceService.class);
        if (deviceService == null) {
            return null;
        }
        FlowStatisticService flowStatsService = get(FlowStatisticService.class);
        if (flowStatsService == null) {
            return null;
        }
        FlowRuleService flowService = get(FlowRuleService.class);
        if (flowService == null) {
            return null;
        }
        WorkPartitionService workPartitionService = get(WorkPartitionService.class);
        if (workPartitionService == null) {
            return null;
        }
        ObjectiveTrackerService objectiveTrackerService = get(ObjectiveTrackerService.class);
        if (objectiveTrackerService == null) {
            return null;
        }

        return new ServiceRefs(
                intentsService,
                deviceService,
                flowService,
                workPartitionService,
                objectiveTrackerService
        );
    }

    private static final class ServiceRefs {

        private IntentService intentsService;
        private DeviceService deviceService;
        private FlowRuleService flowService;
        private WorkPartitionService workPartitionService;
        private ObjectiveTrackerService objectiveTrackerService;

        private ServiceRefs(
                IntentService intentsService,
                DeviceService deviceService,
                FlowRuleService flowService,
                WorkPartitionService workPartitionService,
                ObjectiveTrackerService objectiveTrackerService
        ) {
            this.intentsService = intentsService;
            this.deviceService = deviceService;
            this.flowService = flowService;
            this.workPartitionService = workPartitionService;
            this.objectiveTrackerService = objectiveTrackerService;
        }

        public IntentService intentsService() {
            return intentsService;
        }

        public DeviceService deviceService() {
            return deviceService;
        }

        public FlowRuleService flowService() {
            return flowService;
        }

        public WorkPartitionService getWorkPartitionService() {
            return workPartitionService;
        }

        public ObjectiveTrackerService getObjectiveTrackerService() {
            return objectiveTrackerService;
        }
    }

}
