/*
 * Copyright 2019-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.k8snetworking.util;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.ContainerPort;
import io.fabric8.kubernetes.api.model.Namespace;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.util.SubnetUtils;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onosproject.cfg.ConfigProperty;
import org.onosproject.k8snetworking.api.DefaultK8sPort;
import org.onosproject.k8snetworking.api.K8sNamespaceService;
import org.onosproject.k8snetworking.api.K8sNetwork;
import org.onosproject.k8snetworking.api.K8sNetworkAdminService;
import org.onosproject.k8snetworking.api.K8sNetworkService;
import org.onosproject.k8snetworking.api.K8sPodService;
import org.onosproject.k8snetworking.api.K8sPort;
import org.onosproject.k8snetworking.api.K8sServiceService;
import org.onosproject.k8snode.api.K8sApiConfig;
import org.onosproject.k8snode.api.K8sApiConfigService;
import org.onosproject.k8snode.api.K8sNode;
import org.onosproject.k8snode.api.K8sNodeService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.group.DefaultGroupKey;
import org.onosproject.net.group.GroupKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static org.onosproject.k8snetworking.api.Constants.DEFAULT_NAMESPACE_HASH;
import static org.onosproject.k8snetworking.api.Constants.PORT_NAME_PREFIX_CONTAINER;
import static org.onosproject.k8snetworking.api.K8sPort.State.INACTIVE;

/**
 * An utility that used in kubernetes networking app.
 */
public final class K8sNetworkingUtil {

    private static final Logger log = LoggerFactory.getLogger(K8sNetworkingUtil.class);

    private static final String COLON_SLASH = "://";
    private static final String COLON = ":";

    private static final String STR_ZERO = "0";
    private static final String STR_ONE = "1";
    private static final String STR_PADDING = "0000000000000000";
    private static final int MASK_BEGIN_IDX = 0;
    private static final int MASK_MAX_IDX = 16;
    private static final int MASK_RADIX = 2;
    private static final int PORT_RADIX = 16;

    private static final String PORT_ID = "portId";
    private static final String DEVICE_ID = "deviceId";
    private static final String PORT_NUMBER = "portNumber";
    private static final String IP_ADDRESS = "ipAddress";
    private static final String MAC_ADDRESS = "macAddress";
    private static final String NETWORK_ID = "networkId";

    private K8sNetworkingUtil() {
    }

    /**
     * Checks that whether the port is associated with container interface.
     *
     * @param portName      port name
     * @return true if the port is associated with container; false otherwise
     */
    public static boolean isContainer(String portName) {
        return portName != null && portName.contains(PORT_NAME_PREFIX_CONTAINER);
    }

    /**
     * Returns the tunnel port number with specified net ID and kubernetes node.
     *
     * @param netId         network ID
     * @param netService    network service
     * @param node          kubernetes node
     * @return tunnel port number
     */
    public static PortNumber tunnelPortNumByNetId(String netId,
                                                  K8sNetworkService netService,
                                                  K8sNode node) {
        K8sNetwork.Type netType = netService.network(netId).type();

        if (netType == null) {
            return null;
        }

        return tunnelPortNumByNetType(netType, node);
    }

    /**
     * Returns the tunnel port number with specified net type and kubernetes node.
     *
     * @param netType       network type
     * @param node          kubernetes node
     * @return tunnel port number
     */
    public static PortNumber tunnelPortNumByNetType(K8sNetwork.Type netType,
                                                    K8sNode node) {
        switch (netType) {
            case VXLAN:
                return node.vxlanPortNum();
            case GRE:
                return node.grePortNum();
            case GENEVE:
                return node.genevePortNum();
            default:
                return null;
        }
    }

    /**
     * Obtains the property value with specified property key name.
     *
     * @param properties    a collection of properties
     * @param name          key name
     * @return mapping value
     */
    public static String getPropertyValue(Set<ConfigProperty> properties,
                                          String name) {
        Optional<ConfigProperty> property =
                properties.stream().filter(p -> p.name().equals(name)).findFirst();
        return property.map(ConfigProperty::value).orElse(null);
    }

    /**
     * Prints out the JSON string in pretty format.
     *
     * @param mapper        Object mapper
     * @param jsonString    JSON string
     * @return pretty formatted JSON string
     */
    public static String prettyJson(ObjectMapper mapper, String jsonString) {
        try {
            Object jsonObject = mapper.readValue(jsonString, Object.class);
            return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject);
        } catch (JsonParseException e) {
            log.debug("JsonParseException", e);
        } catch (JsonMappingException e) {
            log.debug("JsonMappingException", e);
        } catch (JsonProcessingException e) {
            log.debug("JsonProcessingException", e);
        } catch (IOException e) {
            log.debug("IOException", e);
        }
        return null;
    }

    /**
     * Obtains valid IP addresses of the given subnet.
     *
     * @param cidr CIDR
     * @return set of IP addresses
     */
    public static Set<IpAddress> getSubnetIps(String cidr) {
        SubnetUtils utils = new SubnetUtils(cidr);
        utils.setInclusiveHostCount(false);
        SubnetUtils.SubnetInfo info = utils.getInfo();
        Set<String> allAddresses =
                new HashSet<>(Arrays.asList(info.getAllAddresses()));

        if (allAddresses.size() > 2) {
            allAddresses.remove(info.getLowAddress());
            allAddresses.remove(info.getHighAddress());
        }

        return allAddresses.stream()
                .map(IpAddress::valueOf).collect(Collectors.toSet());
    }

    /**
     * Obtains flow group key from the given id.
     *
     * @param groupId flow group identifier
     * @return flow group key
     */
    public static GroupKey getGroupKey(int groupId) {
        return new DefaultGroupKey((Integer.toString(groupId)).getBytes());
    }

    /**
     * Generates endpoint URL by referring to scheme, ipAddress and port.
     *
     * @param scheme        scheme
     * @param ipAddress     IP address
     * @param port          port number
     * @return generated endpoint URL
     */
    public static String endpoint(K8sApiConfig.Scheme scheme, IpAddress ipAddress, int port) {
        StringBuilder endpoint = new StringBuilder();
        String protocol = StringUtils.lowerCase(scheme.name());

        endpoint.append(protocol);
        endpoint.append(COLON_SLASH);
        endpoint.append(ipAddress.toString());
        endpoint.append(COLON);
        endpoint.append(port);

        return endpoint.toString();
    }

    /**
     * Generates endpoint URL by referring to scheme, ipAddress and port.
     *
     * @param apiConfig     kubernetes API config
     * @return generated endpoint URL
     */
    public static String endpoint(K8sApiConfig apiConfig) {
        return endpoint(apiConfig.scheme(), apiConfig.ipAddress(), apiConfig.port());
    }

    /**
     * Obtains workable kubernetes client.
     *
     * @param config kubernetes API config
     * @return kubernetes client
     */
    public static KubernetesClient k8sClient(K8sApiConfig config) {
        if (config == null) {
            log.warn("Kubernetes API server config is empty.");
            return null;
        }

        String endpoint = endpoint(config);

        ConfigBuilder configBuilder = new ConfigBuilder().withMasterUrl(endpoint);

        if (config.scheme() == K8sApiConfig.Scheme.HTTPS) {
            configBuilder.withTrustCerts(true)
                    .withOauthToken(config.token())
                    .withCaCertData(config.caCertData())
                    .withClientCertData(config.clientCertData())
                    .withClientKeyData(config.clientKeyData());
        }

        return new DefaultKubernetesClient(configBuilder.build());
    }

    /**
     * Obtains workable kubernetes client.
     *
     * @param service kubernetes API service
     * @return kubernetes client
     */
    public static KubernetesClient k8sClient(K8sApiConfigService service) {
        K8sApiConfig config =
                service.apiConfigs().stream().findAny().orElse(null);
        if (config == null) {
            log.error("Failed to find valid kubernetes API configuration.");
            return null;
        }

        KubernetesClient client = k8sClient(config);

        if (client == null) {
            log.error("Failed to connect to kubernetes API server.");
            return null;
        }

        return client;
    }

    /**
     * Obtains the kubernetes node IP and kubernetes network gateway IP map.
     *
     * @param nodeService       kubernetes node service
     * @param networkService    kubernetes network service
     * @return kubernetes node IP and kubernetes network gateway IP map
     */
    public static Map<String, String> nodeIpGatewayIpMap(K8sNodeService nodeService,
                                                         K8sNetworkService networkService) {
        Map<String, String> ipMap = Maps.newConcurrentMap();

        nodeService.completeNodes().forEach(n -> {
            K8sNetwork network = networkService.network(n.hostname());
            if (network != null) {
                ipMap.put(n.dataIp().toString(), network.gatewayIp().toString());
            }
        });

        return ipMap;
    }

    /**
     * Returns a shifted IP address.
     *
     * @param ipAddress     IP address to be shifted
     * @param shiftPrefix   A IP prefix used in shifted IP address
     * @return shifted Ip address
     */
    public static String shiftIpDomain(String ipAddress, String shiftPrefix) {
        String origIpPrefix = ipAddress.split("\\.")[0] + "." + ipAddress.split("\\.")[1];
        return StringUtils.replace(ipAddress, origIpPrefix, shiftPrefix);
    }

    /**
     * Returns an unshifted IP address.
     *
     * @param ipAddress     IP address to be unshifted
     * @param ipPrefix      IP prefix which to be used for unshifting
     * @param cidr          a POD network CIDR
     * @return unshifted IP address
     */
    public static String unshiftIpDomain(String ipAddress,
                                         String ipPrefix,
                                         String cidr) {

        String origIpPrefix = cidr.split("\\.")[0] + "." + cidr.split("\\.")[1];
        return StringUtils.replace(ipAddress, ipPrefix, origIpPrefix);
    }

    /**
     * Returns the B class IP prefix of the given CIDR.
     *
     * @param cidr  CIDR
     * @return IP prefix
     */
    public static String getBclassIpPrefixFromCidr(String cidr) {
        if (cidr == null) {
            return null;
        }
        return cidr.split("\\.")[0] + "." + cidr.split("\\.")[1];
    }

    /**
     * Returns the A class IP prefix of the given CIDR.
     *
     * @param cidr  CIDR
     * @return IP prefix
     */
    public static String getAclassIpPrefixFromCidr(String cidr) {
        if (cidr == null) {
            return null;
        }
        return cidr.split("\\.")[0];
    }

    /**
     * Returns the map of port range.
     *
     * @param portMin minimum port number
     * @param portMax maximum port number
     * @return map of port range
     */
    public static Map<TpPort, TpPort> buildPortRangeMatches(int portMin, int portMax) {

        boolean processing = true;
        int start = portMin;
        Map<TpPort, TpPort> portMaskMap = Maps.newHashMap();
        while (processing) {
            String minStr = Integer.toBinaryString(start);
            String binStrMinPadded = STR_PADDING.substring(minStr.length()) + minStr;

            int mask = testMasks(binStrMinPadded, start, portMax);
            int maskStart = binLower(binStrMinPadded, mask);
            int maskEnd = binHigher(binStrMinPadded, mask);

            log.debug("start : {} port/mask = {} / {} ", start, getMask(mask), maskStart);
            portMaskMap.put(TpPort.tpPort(maskStart), TpPort.tpPort(
                    Integer.parseInt(Objects.requireNonNull(getMask(mask)), PORT_RADIX)));

            start = maskEnd + 1;
            if (start > portMax) {
                processing = false;
            }
        }

        return portMaskMap;
    }

    /**
     * Returns the namespace hash value by given POD IP.
     *
     * @param k8sPodService         kubernetes POD service
     * @param k8sNamespaceService   kubernetes namespace service
     * @param podIp                 POD IP address
     * @return namespace hash value
     */
    public static Integer namespaceHashByPodIp(K8sPodService k8sPodService,
                                               K8sNamespaceService k8sNamespaceService,
                                               String podIp) {
        String ns = k8sPodService.pods().stream()
                .filter(pod -> pod.getStatus().getPodIP() != null)
                .filter(pod -> pod.getStatus().getPodIP().equals(podIp))
                .map(pod -> pod.getMetadata().getNamespace())
                .findAny().orElse(null);

        if (ns != null) {
            return k8sNamespaceService.namespaces().stream()
                    .filter(n -> n.getMetadata().getName().equals(ns))
                    .map(Namespace::hashCode).findAny().orElse(null);
        } else {
            return null;
        }
    }

    /**
     * Returns the namespace hash value by given service IP.
     *
     * @param k8sServiceService     kubernetes service service
     * @param k8sNamespaceService   kubernetes namespace service
     * @param serviceIp             service IP address
     * @return namespace hash value
     */
    public static int namespaceHashByServiceIp(K8sServiceService k8sServiceService,
                                                   K8sNamespaceService k8sNamespaceService,
                                                   String serviceIp) {
        String ns = k8sServiceService.services().stream()
                .filter(service -> service.getSpec().getClusterIP() != null)
                .filter(service -> service.getSpec().getClusterIP().equalsIgnoreCase(serviceIp))
                .map(service -> service.getMetadata().getNamespace())
                .findAny().orElse(null);

        if (ns != null) {
            return namespaceHashByNamespace(k8sNamespaceService, ns);
        } else {
            return DEFAULT_NAMESPACE_HASH;
        }
    }

    /**
     * Returns the namespace hash value by given namespace name.
     *
     * @param k8sNamespaceService   kubernetes namespace service
     * @param ns                    namespace name
     * @return namespace hash value
     */
    public static int namespaceHashByNamespace(K8sNamespaceService k8sNamespaceService,
                                               String ns) {

        return k8sNamespaceService.namespaces().stream()
                .filter(n -> n.getMetadata().getName() != null)
                .filter(n -> n.getMetadata().getName().equalsIgnoreCase(ns))
                .map(Namespace::hashCode).findAny().orElse(DEFAULT_NAMESPACE_HASH);
    }

    /**
     * Returns POD instance by POD IP address.
     *
     * @param podService    kubernetes POD service
     * @param podIp         POD IP address
     * @return POD instance
     */
    public static Pod podByIp(K8sPodService podService, String podIp) {
        return podService.pods().stream()
                .filter(pod -> pod.getStatus().getPodIP() != null)
                .filter(pod -> pod.getStatus().getPodIP().equals(podIp))
                .findAny().orElse(null);
    }

    /**
     * Returns the container port number by given container port name.
     *
     * @param pod           kubernetes POD
     * @param portName      port name
     * @return container port number,
     *         return 0 if there is no port number mapped with the given port name
     */
    public static int portNumberByName(Pod pod, String portName) {

        if (pod == null || pod.getSpec() == null) {
            return 0;
        }

        for (Container container : pod.getSpec().getContainers()) {
            for (ContainerPort cp : container.getPorts()) {
                if (cp.getName() != null && cp.getName().equals(portName)) {
                    return cp.getContainerPort();
                }
            }
        }

        return 0;
    }

    /**
     * Synchronizes port from kubernetes POD.
     *
     * @param pod               kubernetes POD
     * @param adminService      admin service
     */
    public static void syncPortFromPod(Pod pod, K8sNetworkAdminService adminService) {
        Map<String, String> annotations = pod.getMetadata().getAnnotations();
        if (annotations != null && !annotations.isEmpty() &&
                annotations.get(PORT_ID) != null) {
            String portId = annotations.get(PORT_ID);

            K8sPort oldPort = adminService.port(portId);

            String networkId = annotations.get(NETWORK_ID);
            DeviceId deviceId = DeviceId.deviceId(annotations.get(DEVICE_ID));
            PortNumber portNumber = PortNumber.portNumber(annotations.get(PORT_NUMBER));
            IpAddress ipAddress = IpAddress.valueOf(annotations.get(IP_ADDRESS));
            MacAddress macAddress = MacAddress.valueOf(annotations.get(MAC_ADDRESS));

            K8sPort newPort = DefaultK8sPort.builder()
                    .portId(portId)
                    .networkId(networkId)
                    .deviceId(deviceId)
                    .ipAddress(ipAddress)
                    .macAddress(macAddress)
                    .portNumber(portNumber)
                    .state(INACTIVE)
                    .build();

            if (oldPort == null) {
                adminService.createPort(newPort);
            } else {
                adminService.updatePort(newPort);
            }
        }
    }

    private static int binLower(String binStr, int bits) {
        StringBuilder outBin = new StringBuilder(
                binStr.substring(MASK_BEGIN_IDX, MASK_MAX_IDX - bits));
        for (int i = 0; i < bits; i++) {
            outBin.append(STR_ZERO);
        }

        return Integer.parseInt(outBin.toString(), MASK_RADIX);
    }

    private static int binHigher(String binStr, int bits) {
        StringBuilder outBin = new StringBuilder(
                binStr.substring(MASK_BEGIN_IDX, MASK_MAX_IDX - bits));
        for (int i = 0; i < bits; i++) {
            outBin.append(STR_ONE);
        }

        return Integer.parseInt(outBin.toString(), MASK_RADIX);
    }

    private static int testMasks(String binStr, int start, int end) {
        int mask = MASK_BEGIN_IDX;
        for (; mask <= MASK_MAX_IDX; mask++) {
            int maskStart = binLower(binStr, mask);
            int maskEnd = binHigher(binStr, mask);
            if (maskStart < start || maskEnd > end) {
                return mask - 1;
            }
        }

        return mask;
    }

    private static String getMask(int bits) {
        switch (bits) {
            case 0:  return "ffff";
            case 1:  return "fffe";
            case 2:  return "fffc";
            case 3:  return "fff8";
            case 4:  return "fff0";
            case 5:  return "ffe0";
            case 6:  return "ffc0";
            case 7:  return "ff80";
            case 8:  return "ff00";
            case 9:  return "fe00";
            case 10: return "fc00";
            case 11: return "f800";
            case 12: return "f000";
            case 13: return "e000";
            case 14: return "c000";
            case 15: return "8000";
            case 16: return "0000";
            default: return null;
        }
    }
}
