/*
 * 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) {
        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) {

        try {

            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());
        } catch (NoSuchFieldException | IllegalAccessException ex) {
            error("error: " + ex);
            return ImmutableSet.of();
        }
    }

    private void diagnosisP2Pintent(PointToPointIntent intent, ServiceRefs svcRefs) {

        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) {

        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) {

        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);
                            dev.addEgressLink(link);

                            dev = devMap.computeIfAbsent(dstCp.deviceId(), DeviceOnIntent::new);
                            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);
        }

        @Override
        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;
        }
    }

}
