/*
 * Copyright 2015-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.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.DeviceId;
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.opencord.cordvtn.impl.DefaultCordVtnNode;
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 localMgmtIp = CidrAddr.valueOf(get(LOCAL_MANAGEMENT_IP, ""));
            CidrAddr hostsMgmtIp = CidrAddr.valueOf(getConfig(vtnNode, HOST_MANAGEMENT_IP));

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

            CordVtnNode.Builder nodeBuilder = DefaultCordVtnNode.builder()
                    .hostname(getConfig(vtnNode, HOSTNAME))
                    .hostManagementIp(hostsMgmtIp)
                    .localManagementIp(localMgmtIp)
                    .dataIp(CidrAddr.valueOf(getConfig(vtnNode, DATA_IP)))
                    .sshInfo(sshInfo)
                    .integrationBridgeId(DeviceId.deviceId(getConfig(vtnNode, INTEGRATION_BRIDGE_ID)))
                    .dataInterface(getConfig(vtnNode, DATA_IFACE));

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

            String hostMgmtIface = getConfig(vtnNode, HOST_MANAGEMENT_IFACE);
            if (!Strings.isNullOrEmpty(hostMgmtIface)) {
                nodeBuilder.hostManagementInterface(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]);
    }
}
