/*
 * 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());

    @Deprecated
    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 && 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 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]);
    }
}
