/*
 * 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.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.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;

@Service
@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 doExecute() {

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

}
