/*
 * Copyright 2017-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.dhcprelay.cli;


import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.Tools;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.dhcprelay.store.DhcpRelayCounters;
import org.onosproject.dhcprelay.api.DhcpServerInfo;
import org.onosproject.dhcprelay.api.DhcpRelayService;
import org.onosproject.dhcprelay.store.DhcpRecord;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.host.HostService;

import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;
import java.util.Map;


/**
 * Prints DHCP server and DHCP relay status.
 */
@Command(scope = "onos", name = "dhcp-relay", description = "DHCP relay app cli.")
public class DhcpRelayCommand extends AbstractShellCommand {
    @Argument(index = 0, name = "counter",
            description = "shows counter values",
            required = false, multiValued = false)
    String counter = null;

    @Argument(index = 1, name = "reset",
            description = "reset counters or not",
            required = false, multiValued = false)
    String reset = null;



    private static final String CONUTER_HEADER = "DHCP Relay Counters :";
    private static final String COUNTER_HOST = "Counters for id=%s/%s, locations=%s%s";


    private static final String HEADER = "DHCP relay records ([D]: Directly connected):";
    private static final String NO_RECORDS = "No DHCP relay record found";
    private static final String HOST = "id=%s/%s, locations=%s%s, last-seen=%s, IPv4=%s, IPv6=%s";
    private static final String DHCP_SERVER_GW = "DHCP Server: %s, %s via %s (Mac: %s)";
    private static final String DHCP_SERVER = "DHCP Server: %s, %s (Mac: %s)";
    private static final String MISSING_SERVER_CFG = "DHCP Server info not available";
    private static final String DIRECTLY = "[D]";
    private static final String EMPTY = "";
    private static final String NA = "N/A";
    private static final String STATUS_FMT = "[%s, %s]";
    private static final String STATUS_FMT_NH = "[%s via %s, %s]";
    private static final String STATUS_FMT_V6 = "[%s %d, %d ms %s %d %d ms, %s]";
    private static final String STATUS_FMT_V6_NH = "[%s %d %d ms, %s %d %d ms via %s, %s]";
    private static final String DEFAULT_SERVERS = "Default DHCP servers:";
    private static final String INDIRECT_SERVERS = "Indirect DHCP servers:";

    private static final DhcpRelayService DHCP_RELAY_SERVICE = get(DhcpRelayService.class);
    private static final HostService HOST_SERVICE = get(HostService.class);


    @Override
    protected void execute() {
        List<DhcpServerInfo> defaultDhcpServerInfoList = DHCP_RELAY_SERVICE.getDefaultDhcpServerInfoList();
        List<DhcpServerInfo> indirectDhcpServerInfoList = DHCP_RELAY_SERVICE.getIndirectDhcpServerInfoList();

        if (defaultDhcpServerInfoList.isEmpty() && indirectDhcpServerInfoList.isEmpty()) {
            print(MISSING_SERVER_CFG);
            return;
        }

        if (!defaultDhcpServerInfoList.isEmpty()) {
            print(DEFAULT_SERVERS);
            listServers(defaultDhcpServerInfoList);
        }
        if (!indirectDhcpServerInfoList.isEmpty()) {
            print(INDIRECT_SERVERS);
            listServers(indirectDhcpServerInfoList);
        }

        // DHCP records
        Collection<DhcpRecord> records = DHCP_RELAY_SERVICE.getDhcpRecords();
        if (records.isEmpty()) {
            print(NO_RECORDS);
            return;
        }

        // Handle display of counters
        boolean toResetFlag;

        if (counter != null) {
            if (counter.equals("counter") || counter.equals("[counter]")) {
                print(CONUTER_HEADER);
            } else {
                print("first parameter is [counter]");
                return;
            }
            if (reset != null) {
                if (reset.equals("reset") || reset.equals("[reset]")) {
                    toResetFlag = true;
                } else {
                    print("Last parameter is [reset]");
                    return;
                }
            } else {
                toResetFlag = false;
            }

            records.forEach(record -> {
                print(COUNTER_HOST, record.macAddress(),
                        record.vlanId(),
                        record.locations(),
                        record.directlyConnected() ? DIRECTLY : EMPTY);
                DhcpRelayCounters v6Counters = record.getV6Counters();
                Map<String, Integer> countersMap = v6Counters.getCounters();
                countersMap.forEach((name, value) -> {
                    print("%-30s  ............................  %-4d packets", name, value);
                });
                if (toResetFlag) {
                    v6Counters.resetCounters();
                    record.updateLastSeen();
                    DHCP_RELAY_SERVICE.updateDhcpRecord(HostId.hostId(record.macAddress(), record.vlanId()), record);
                }
            });


            return;
        }


        // Handle display of records

        print(HEADER);
        records.forEach(record -> print(HOST,
                                        record.macAddress(),
                                        record.vlanId(),
                                        record.locations(),
                                        record.directlyConnected() ? DIRECTLY : EMPTY,
                                        Tools.timeAgo(record.lastSeen()),
                                        ip4State(record),
                                        ip6State(record)));
    }

    private void listServers(List<DhcpServerInfo> dhcpServerInfoList) {
        dhcpServerInfoList.forEach(dhcpServerInfo -> {
            String connectPoint = dhcpServerInfo.getDhcpServerConnectPoint()
                    .map(Object::toString).orElse(NA);
            String serverMac = dhcpServerInfo.getDhcpConnectMac()
                    .map(Object::toString).orElse(NA);
            String gatewayAddress;
            String serverIp;

            switch (dhcpServerInfo.getVersion()) {
                case DHCP_V4:
                    gatewayAddress = dhcpServerInfo.getDhcpGatewayIp4()
                            .map(Object::toString).orElse(null);
                    serverIp = dhcpServerInfo.getDhcpServerIp4()
                            .map(Object::toString).orElse(NA);
                    break;
                case DHCP_V6:
                    gatewayAddress = dhcpServerInfo.getDhcpGatewayIp6()
                            .map(Object::toString).orElse(null);
                    serverIp = dhcpServerInfo.getDhcpServerIp6()
                            .map(Object::toString).orElse(NA);
                    break;
                default:
                    return;
            }
            if (gatewayAddress != null) {
                print(DHCP_SERVER_GW, connectPoint, serverIp, gatewayAddress, serverMac);
            } else {
                print(DHCP_SERVER, connectPoint, serverIp, serverMac);
            }
        });
    }

    private String ip4State(DhcpRecord record) {
        String nextHopIp = findNextHopIp(IpAddress::isIp4,
                                         record.nextHop().orElse(null),
                                         record.vlanId());
        return ipState(record.ip4Address().map(Object::toString).orElse(NA),
                       record.ip4Status().map(Object::toString).orElse(NA),
                       record.directlyConnected(),
                       nextHopIp);
    }

    private String ip6State(DhcpRecord record) {
        String nextHopIp = findNextHopIp6(IpAddress::isIp6,
                                         record.nextHop().orElse(null),
                                         record.vlanId());

        if (record.directlyConnected()) {
            return String.format(STATUS_FMT_V6,
                    record.ip6Address().map(Object::toString).orElse(NA),
                    record.addrPrefTime(),
                    record.getLastIp6Update(),
                    record.pdPrefix().map(Object::toString).orElse(NA),
                    record.pdPrefTime(),
                    record.getLastPdUpdate(),
                    record.ip6Status().map(Object::toString).orElse(NA));
        } else {
            return String.format(STATUS_FMT_V6_NH,
                    record.ip6Address().map(Object::toString).orElse(NA),
                    record.addrPrefTime(),
                    record.getLastIp6Update(),
                    record.pdPrefix().map(Object::toString).orElse(NA),
                    record.pdPrefTime(),
                    record.getLastPdUpdate(),
                    nextHopIp,
                    record.ip6Status().map(Object::toString).orElse(NA));
        }
    }

    private String ipState(String ipAddress, String status,
                           boolean directlyConnected,
                           String nextHopIp) {
        if (directlyConnected) {
            return String.format(STATUS_FMT, ipAddress, status);
        } else {
            return String.format(STATUS_FMT_NH, ipAddress, nextHopIp, status);
        }
    }

    private String findNextHopIp(Predicate<IpAddress> ipFilter, MacAddress nextHopMac, VlanId vlanId) {
        if (ipFilter == null || nextHopMac == null || vlanId == null) {
            return NA;
        }

        Host host = HOST_SERVICE.getHost(HostId.hostId(nextHopMac, vlanId));
        if (host == null) {
            return NA;
        }
        return host.ipAddresses().stream()
                .filter(ipFilter)
                .filter(ip -> !ip.isLinkLocal())
                .map(Object::toString)
                .findFirst()
                .orElse(NA);
    }

    private String findNextHopIp6(Predicate<IpAddress> ipFilter, MacAddress nextHopMac, VlanId vlanId) {
        if (ipFilter == null || nextHopMac == null || vlanId == null) {
            return NA;
        }

        Host host = HOST_SERVICE.getHost(HostId.hostId(nextHopMac, vlanId));
        if (host == null) {
            return NA;
        }
        return host.ipAddresses().stream()
                .filter(ipFilter)
                .filter(ip -> ip.isLinkLocal())
                .map(Object::toString)
                .findFirst()
                .orElse(NA);
    }
}
