/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * 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.opencord.cordvtn.api;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onlab.osgi.DefaultServiceDirectory;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onosproject.cluster.ClusterService;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.behaviour.ControllerInfo;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.InvalidFieldException;
import org.opencord.cordvtn.api.net.CidrAddr;
import org.opencord.cordvtn.api.node.CordVtnNode;
import org.opencord.cordvtn.api.node.SshAccessInfo;
import org.slf4j.Logger;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static org.onosproject.net.config.Config.FieldPresence.MANDATORY;
import static org.onosproject.net.config.Config.FieldPresence.OPTIONAL;
import static org.opencord.cordvtn.api.Constants.DEFAULT_OF_PORT;
import static org.opencord.cordvtn.api.Constants.DEFAULT_OF_PROTOCOL;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Configuration object for CordVtn service.
 */
public class CordVtnConfig extends Config<ApplicationId> {

    protected final Logger log = getLogger(getClass());

    private static final String PRIVATE_GATEWAY_MAC = "privateGatewayMac";
    private static final String PUBLIC_GATEWAYS = "publicGateways";
    private static final String GATEWAY_IP = "gatewayIp";
    private static final String GATEWAY_MAC = "gatewayMac";
    private static final String LOCAL_MANAGEMENT_IP = "localManagementIp";
    private static final String OVSDB_PORT = "ovsdbPort";

    private static final String CORDVTN_NODES = "nodes";
    private static final String HOSTNAME = "hostname";
    private static final String HOST_MANAGEMENT_IP = "hostManagementIp";
    private static final String HOST_MANAGEMENT_IFACE = "hostManagementIface";
    private static final String DATA_IP = "dataPlaneIp";
    private static final String DATA_IFACE = "dataPlaneIntf";
    private static final String INTEGRATION_BRIDGE_ID = "bridgeId";

    private static final String SSH = "ssh";
    private static final String SSH_PORT = "sshPort";
    private static final String SSH_USER = "sshUser";
    private static final String SSH_KEY_FILE = "sshKeyFile";

    @Deprecated
    private static final String OPENSTACK = "openstack";
    @Deprecated
    private static final String XOS = "xos";

    private static final String CONTROLLERS = "controllers";
    private static final int INDEX_IP = 0;
    private static final int INDEX_PORT = 1;

    private final ClusterService clusterService =
            DefaultServiceDirectory.getService(ClusterService.class);

    @Override
    public boolean isValid() {
        // check only allowed fields are present
        boolean result = hasOnlyFields(
                PRIVATE_GATEWAY_MAC,
                PUBLIC_GATEWAYS,
                LOCAL_MANAGEMENT_IP,
                OVSDB_PORT,
                SSH,
                OPENSTACK,
                XOS,
                CORDVTN_NODES,
                CONTROLLERS);

        if (object.get(CORDVTN_NODES) == null || object.get(CORDVTN_NODES).size() < 1) {
            final String msg = "No node is present";
            throw new IllegalArgumentException(msg);
        }

        // check all mandatory fields are present and valid
        result = result && isMacAddress(PRIVATE_GATEWAY_MAC, MANDATORY);
        result = result && isIpPrefix(LOCAL_MANAGEMENT_IP, MANDATORY);

        for (JsonNode node : object.get(CORDVTN_NODES)) {
            ObjectNode vtnNode = (ObjectNode) node;
            result = result && hasFields(
                    vtnNode,
                    HOSTNAME,
                    HOST_MANAGEMENT_IP,
                    DATA_IP,
                    DATA_IFACE,
                    INTEGRATION_BRIDGE_ID);
            result = result && isIpPrefix(vtnNode, HOST_MANAGEMENT_IP, MANDATORY);
            result = result && isIpPrefix(vtnNode, DATA_IP, MANDATORY);

            CidrAddr localMgmt = CidrAddr.valueOf(get(LOCAL_MANAGEMENT_IP, ""));
            CidrAddr hostsMgmt = CidrAddr.valueOf(getConfig(vtnNode, HOST_MANAGEMENT_IP));
            if (hostsMgmt.prefix().contains(localMgmt.prefix()) ||
                    localMgmt.prefix().contains(hostsMgmt.prefix())) {
                final String msg = "Host and local management network IP conflict";
                throw new IllegalArgumentException(msg);
            }
        }

        result = result && hasFields(
                (ObjectNode) object.get(SSH),
                SSH_PORT,
                SSH_USER,
                SSH_KEY_FILE);
        result = result && isTpPort(
                (ObjectNode) object.get(SSH),
                SSH_PORT,
                MANDATORY);

        // check all optional fields are valid
        result = result && isTpPort(OVSDB_PORT, OPTIONAL);

        if (object.get(PUBLIC_GATEWAYS) != null && object.get(PUBLIC_GATEWAYS).isArray()) {
            for (JsonNode node : object.get(PUBLIC_GATEWAYS)) {
                ObjectNode gateway = (ObjectNode) node;
                result = result && isIpAddress(gateway, GATEWAY_IP, MANDATORY);
                result = result && isMacAddress(gateway, GATEWAY_MAC, MANDATORY);
            }
        }

        if (object.get(CONTROLLERS) != null) {
            for (JsonNode jsonNode : object.get(CONTROLLERS)) {
                result = result && isController(jsonNode);
            }
        }
        return result;
    }

    private boolean isController(JsonNode jsonNode) {
        String[] ctrl = jsonNode.asText().split(":");
        final String error = "Malformed controller string " + jsonNode.asText() +
                ". Controller only takes a list of 'IP:port', 'IP', " +
                "or just one ':port'.";
        try {
            if (ctrl.length == 1) {
                IpAddress.valueOf(ctrl[INDEX_IP]);
                return true;
            }
            if (ctrl.length == 2 && ctrl[INDEX_IP].isEmpty() &&
                    object.get(CONTROLLERS).size() == 1) {
                TpPort.tpPort(Integer.valueOf(ctrl[INDEX_PORT]));
                return true;
            }
            if (ctrl.length == 2 && !ctrl[INDEX_IP].isEmpty()) {
                IpAddress.valueOf(ctrl[INDEX_IP]);
                TpPort.tpPort(Integer.valueOf(ctrl[INDEX_PORT]));
                return true;
            }
            throw new InvalidFieldException(CONTROLLERS, error);
        } catch (IllegalArgumentException e) {
            throw new InvalidFieldException(CONTROLLERS, error);
        }
    }

    /**
     * Returns the set of nodes read from network config.
     *
     * @return set of CordVtnNodeConfig or empty set
     */
    public Set<CordVtnNode> cordVtnNodes() {
        Set<CordVtnNode> nodes = Sets.newHashSet();
        JsonNode sshNode = object.get(SSH);
        String ovsdbPort = getConfig(object, OVSDB_PORT);

        object.get(CORDVTN_NODES).forEach(vtnNode -> {
            CidrAddr localMgmt = CidrAddr.valueOf(get(LOCAL_MANAGEMENT_IP, ""));
            CidrAddr hostsMgmt = CidrAddr.valueOf(getConfig(vtnNode, HOST_MANAGEMENT_IP));

            SshAccessInfo sshInfo = new SshAccessInfo(
                    hostsMgmt.ip().getIp4Address(),
                    TpPort.tpPort(Integer.parseInt(getConfig(sshNode, SSH_PORT))),
                    getConfig(sshNode, SSH_USER),
                    getConfig(sshNode, SSH_KEY_FILE));

            CordVtnNode.Builder nodeBuilder = CordVtnNode.builder()
                    .hostname(getConfig(vtnNode, HOSTNAME))
                    .hostMgmtIp(hostsMgmt)
                    .localMgmtIp(localMgmt)
                    .dataIp(getConfig(vtnNode, DATA_IP))
                    .sshInfo(sshInfo)
                    .integrationBridgeId(getConfig(vtnNode, INTEGRATION_BRIDGE_ID))
                    .dataIface(getConfig(vtnNode, DATA_IFACE));

            if (!Strings.isNullOrEmpty(ovsdbPort)) {
                nodeBuilder.ovsdbPort(Integer.parseInt(ovsdbPort));
            }

            String hostMgmtIface = getConfig(vtnNode, HOST_MANAGEMENT_IFACE);
            if (!Strings.isNullOrEmpty(hostMgmtIface)) {
                nodeBuilder.hostMgmtIface(hostMgmtIface);
            }

            nodes.add(nodeBuilder.build());
        });

        return nodes;
    }

    /**
     * Gets the specified property as a string.
     *
     * @param jsonNode node whose fields to get
     * @param path property to get
     * @return value as a string
     */
    private String getConfig(JsonNode jsonNode, String path) {
        jsonNode = jsonNode.path(path);
        return jsonNode.asText();
    }

    /**
     * Returns private network gateway MAC address.
     *
     * @return mac address
     */
    public MacAddress privateGatewayMac() {
        JsonNode jsonNode = object.get(PRIVATE_GATEWAY_MAC);
        return MacAddress.valueOf(jsonNode.asText());
    }

    /**
     * Returns public network gateway IP and MAC address pairs.
     *
     * @return map of ip and mac address
     */
    public Map<IpAddress, MacAddress> publicGateways() {
        JsonNode jsonNodes = object.get(PUBLIC_GATEWAYS);
        Map<IpAddress, MacAddress> publicGateways = Maps.newHashMap();

        if (jsonNodes == null) {
            return publicGateways;
        }

        jsonNodes.forEach(jsonNode -> publicGateways.put(
                IpAddress.valueOf(jsonNode.path(GATEWAY_IP).asText()),
                MacAddress.valueOf(jsonNode.path(GATEWAY_MAC).asText())));
        return publicGateways;
    }

    /**
     * Returns controllers for the integration bridge.
     * It returns the information taken from cluster service with the default OF
     * port if no controller is specified in the network config.
     *
     * @return list of controller information
     */
    public List<ControllerInfo> controllers() {
        List<ControllerInfo> ctrls = Lists.newArrayList();
        JsonNode ctrlNodes = object.get(CONTROLLERS);

        if (ctrlNodes == null || isCtrlPortOnly()) {
            ctrls = clusterService.getNodes().stream()
                    .map(ctrl -> new ControllerInfo(
                            ctrl.ip(),
                            ctrlNodes == null ? DEFAULT_OF_PORT : getCtrlPort(),
                            DEFAULT_OF_PROTOCOL))
                    .collect(Collectors.toList());
        } else {
            for (JsonNode ctrlNode : ctrlNodes) {
                String[] ctrl = ctrlNode.asText().split(":");
                ctrls.add(new ControllerInfo(
                        IpAddress.valueOf(ctrl[INDEX_IP]),
                        ctrl.length == 1 ? DEFAULT_OF_PORT :
                                Integer.parseInt(ctrl[INDEX_PORT]),
                        DEFAULT_OF_PROTOCOL));
            }
        }
        return ImmutableList.copyOf(ctrls);
    }

    private boolean isCtrlPortOnly() {
        if (object.get(CONTROLLERS).size() != 1) {
            return false;
        }
        JsonNode jsonNode = object.get(CONTROLLERS).get(0);
        String[] ctrl = jsonNode.asText().split(":");
        return ctrl.length == 2 && ctrl[INDEX_IP].isEmpty();
    }

    private int getCtrlPort() {
        JsonNode jsonNode = object.get(CONTROLLERS).get(0);
        String[] ctrl = jsonNode.asText().split(":");
        return Integer.parseInt(ctrl[INDEX_PORT]);
    }
}
