/*
 * Copyright 2018-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.t3.cli;

import org.apache.commons.lang.StringUtils;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Completion;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.onlab.packet.IpAddress;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cli.PlaceholderCompleter;
import org.onosproject.cli.net.EthTypeCompleter;
import org.onosproject.net.Host;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.t3.api.StaticPacketTrace;
import org.onosproject.t3.api.TroubleshootService;
import org.onosproject.t3.impl.Generator;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static java.lang.Thread.sleep;
import static org.onlab.packet.EthType.EtherType;

/**
 * Starts a Static Packet Trace for a given input and prints the result.
 */
@Service
@Command(scope = "onos", name = "t3-troubleshoot-pingall",
        description = "Traces a ping between all hosts in the system of a given ETH type")
public class TroubleshootPingAllCommand extends AbstractShellCommand {

    private static final String FMT_SHORT =
            "id=%s, mac=%s, locations=%s, vlan=%s, ip(s)=%s";

    @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
    @Completion(EthTypeCompleter.class)
    String ethType = "ipv4";

    @Option(name = "-v", aliases = "--verbose", description = "Outputs trace for each host to host combination")
    @Completion(PlaceholderCompleter.class)
    private boolean verbosity1 = false;

    @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs details of every trace")
    @Completion(PlaceholderCompleter.class)
    private boolean verbosity2 = false;

    @Option(name = "-d", aliases = "--delay", description = "delay between host to host trace display")
    @Completion(PlaceholderCompleter.class)
    private long delay = 0;

    @Override
    protected void doExecute() {
        TroubleshootService service = get(TroubleshootService.class);
        if (service.checkNibsUnavailable()) {
            print(TroubleshootLoadFileCommand.ERROR_NULL);
            return;
        }

        EtherType type = EtherType.valueOf(ethType.toUpperCase());

        print("Tracing between all %s hosts", ethType);

        if (!type.equals(EtherType.IPV4) && !type.equals(EtherType.IPV6)) {
            print("Command only support IPv4 or IPv6");
        } else {
            //Create the generator for the list of traces.
            Generator<Set<StaticPacketTrace>> generator = service.pingAllGenerator(type);
            Host previousHost = null;
            int totalTraces = 0;
            List<StaticPacketTrace> failedTraces = new ArrayList<>();
            boolean ipv4 = type.equals(EtherType.IPV4);
            while (generator.iterator().hasNext()) {
                Set<StaticPacketTrace> traces = generator.iterator().next();
                totalTraces++;
                for (StaticPacketTrace trace : traces) {
                    //no verbosity is mininet style output
                    if (!verbosity1 && !verbosity2) {
                        if (trace.getEndpointHosts().isPresent()) {
                            Host src = trace.getEndpointHosts().get().getLeft();
                            if (previousHost == null || !previousHost.equals(src)) {
                                print("%s", StringUtils.rightPad("", 125, '-'));
                                previousHost = printSrc(trace, ipv4, src);
                            }
                            String host = getDstString(trace, ipv4, src);
                            if (!trace.isSuccess()) {
                                host = host + " " + trace.resultMessage();
                                failedTraces.add(trace);
                            }
                            print("%s", host);
                        }
                    } else {
                        print("%s", StringUtils.leftPad("", 125, '-'));

                        if (trace.getInitialPacket() != null) {
                            if (verbosity1) {
                                printResultOnly(trace, ipv4);
                            } else if (verbosity2) {
                                printVerbose(trace);
                            }
                        } else {
                            if (trace.getEndpointHosts().isPresent()) {
                                Host source = trace.getEndpointHosts().get().getLeft();
                                Host destination = trace.getEndpointHosts().get().getRight();
                                print("Source %s --> Destination %s", source.id(), destination.id());
                            }
                            print("Error in obtaining trace: %s", trace.resultMessage());
                        }
                    }
                }
                try {
                    sleep(delay);
                } catch (InterruptedException e) {
                    log.debug("interrupted while sleep");
                }
            }
            print("%s", StringUtils.rightPad("", 125, '-'));
            print("Failed Traces: %s", failedTraces.size());
            print("%s", StringUtils.rightPad("", 125, '-'));
            failedTraces.forEach(t -> {
                if (t.getEndpointHosts().isPresent()) {
                    printSrc(t, ipv4, t.getEndpointHosts().get().getLeft());
                    String dst = getDstString(t, ipv4, t.getEndpointHosts().get().getRight());
                    dst = dst + " " + t.resultMessage();
                    print("%s", dst);
                    print("%s", StringUtils.rightPad("", 125, '-'));
                }
            });
            print("Summary");
            print("Total Traces %s, errors %s", totalTraces, failedTraces.size());
        }
    }

    private String getDstString(StaticPacketTrace trace, boolean ipv4, Host src) {
        String host;
        IpAddress ipAddress = getIpAddress(trace, ipv4, src, false);
        if (ipAddress == null) {
            host = String.format("       %s %s", trace.getEndpointHosts().get().getRight().id(),
                    trace.isSuccess());
        } else {
            host = String.format("       %s (%s) %s",
                    trace.getEndpointHosts().get().getRight().id(), ipAddress,
                    trace.isSuccess());
        }
        return host;
    }

    private Host printSrc(StaticPacketTrace trace, boolean ipv4, Host src) {
        Host previousHost;
        IpAddress ipAddress = getIpAddress(trace, ipv4, src, true);
        if (ipAddress == null) {
            print("%s", src.id() + " -->");
        } else {
            print("%s (%s) -->", src.id(), ipAddress);
        }
        previousHost = src;
        return previousHost;
    }

    private IpAddress getIpAddress(StaticPacketTrace trace, boolean ipv4, Host host, boolean src) {
        IpAddress ipAddress;
        if (ipv4) {
            Criterion.Type type = src ? Criterion.Type.IPV4_SRC : Criterion.Type.IPV4_DST;
            if (trace.getInitialPacket() != null && trace.getInitialPacket().getCriterion(type) != null) {
                ipAddress = ((IPCriterion) trace.getInitialPacket()
                        .getCriterion(type)).ip().address();
            } else {
                ipAddress = host.ipAddresses().stream().filter(IpAddress::isIp4)
                        .findAny().orElse(null);
            }
        } else {
            Criterion.Type type = src ? Criterion.Type.IPV6_SRC : Criterion.Type.IPV6_DST;
            if (trace.getInitialPacket() != null && trace.getInitialPacket().getCriterion(type) != null) {
                ipAddress = ((IPCriterion) trace.getInitialPacket()
                        .getCriterion(type)).ip().address();
            } else {
                ipAddress = host.ipAddresses().stream().filter(IpAddress::isIp6)
                        .findAny().orElse(null);
            }
        }
        return ipAddress;
    }

    private void printResultOnly(StaticPacketTrace trace, boolean ipv4) {
        if (trace.getEndpointHosts().isPresent()) {
            Host source = trace.getEndpointHosts().get().getLeft();
            Host destination = trace.getEndpointHosts().get().getRight();
            IpAddress srcIP;
            IpAddress dstIP;
            if (ipv4 && trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_SRC) != null) {
                srcIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_SRC)).ip().address();
                dstIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_DST)).ip().address();
                print("Source %s (%s) --> Destination %s (%s)", source.id(), srcIP, destination.id(), dstIP);
            } else if (trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_SRC) != null) {
                srcIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_SRC)).ip().address();
                dstIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_DST)).ip().address();
                print("Source %s (%s) --> Destination %s (%s)", source.id(), srcIP, destination.id(), dstIP);
            } else {
                print("Source %s --> Destination %s", source.id(), destination.id());
            }
            print("%s", trace.resultMessage());
        } else {
            print("Can't gather host information from trace");
            print("%s", trace.resultMessage());
        }
    }

    private void printVerbose(StaticPacketTrace trace) {
        if (trace.getEndpointHosts().isPresent()) {
            Host source = trace.getEndpointHosts().get().getLeft();
            print("Source host %s", printHost(source));
            Host destination = trace.getEndpointHosts().get().getRight();
            print("Destination host %s", printHost(destination));
        }
        print("%s", trace.getInitialPacket());
        print("%s", T3CliUtils.printTrace(trace, false, false));
    }

    private String printHost(Host host) {
        return String.format(FMT_SHORT, host.id(), host.mac(),
                host.locations(),
                host.vlan(), host.ipAddresses());
    }
}
