/*
 * Copyright 2016-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.segmentrouting.config;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.ImmutableSet;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Set;

import static com.google.common.base.MoreObjects.toStringHelper;

/**
 * App configuration object for Segment Routing.
 */
public class SegmentRoutingAppConfig extends Config<ApplicationId> {

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

    private static final String VROUTER_MACS = "vRouterMacs";
    private static final String SUPPRESS_SUBNET = "suppressSubnet";
    private static final String SUPPRESS_HOST_BY_PORT = "suppressHostByPort";
    // TODO We might want to move SUPPRESS_HOST_BY_PROVIDER to Component Config
    private static final String SUPPRESS_HOST_BY_PROVIDER = "suppressHostByProvider";
    private static final String MPLS_ECMP = "MPLS-ECMP";
    private static final String BLACKHOLE_IPS = "blackholeIps";

    @Override
    public boolean isValid() {
        return hasOnlyFields(VROUTER_MACS, SUPPRESS_SUBNET,
                SUPPRESS_HOST_BY_PORT, SUPPRESS_HOST_BY_PROVIDER, MPLS_ECMP, BLACKHOLE_IPS) &&
                vRouterMacs() != null &&
                suppressSubnet() != null && suppressHostByPort() != null &&
                suppressHostByProvider() != null &&
                blackholeIPs() != null;
    }

    /**
     * Gets ips to blackhole from the config.
     *
     * @return Set of ips to blackhole, empty is not specified,
     * or null if not valid
     */
    public Set<IpPrefix> blackholeIPs() {
        if (!object.has(BLACKHOLE_IPS)) {
            return ImmutableSet.of();
        }

        ImmutableSet.Builder<IpPrefix> builder = ImmutableSet.builder();
        ArrayNode arrayNode = (ArrayNode) object.path(BLACKHOLE_IPS);
        for (JsonNode jsonNode : arrayNode) {
            IpPrefix address;

            String addrStr = jsonNode.asText(null);
            if (addrStr != null) {
                try {
                    address = IpPrefix.valueOf(addrStr);
                    builder.add(address);
                } catch (IllegalArgumentException e) {
                    log.debug("Not adding {}", jsonNode, e);
                }
            }
        }
        return builder.build();
    }

    /**
     * Sets ips to blackhole to the config.
     *
     * @param blackholeIps a set of ips to blackhole
     * @return this {@link SegmentRoutingAppConfig}
     */
    public SegmentRoutingAppConfig setBalckholeIps(Set<IpPrefix> blackholeIps) {
        if (blackholeIps == null) {
            object.remove(BLACKHOLE_IPS);
        } else {
            ArrayNode arrayNode = mapper.createArrayNode();

            blackholeIps.forEach(ip -> {
                arrayNode.add(ip.toString());
            });

            object.set(BLACKHOLE_IPS, arrayNode);
        }
        return this;
    }

    /**
     * Gets MPLS-ECMP configuration from the config.
     *
     * @return the configuration of MPLS-ECMP. If it is not
     *         specified, the default behavior is false.
     */
    public boolean mplsEcmp() {
        return get(MPLS_ECMP, false);
    }

    /**
     * Sets MPLS-ECMP to the config.
     *
     * @param mplsEcmp the MPLS-ECMP configuration
     * @return this {@link SegmentRoutingAppConfig}
     */
    public SegmentRoutingAppConfig setMplsEcmp(boolean mplsEcmp) {
        object.put(MPLS_ECMP, mplsEcmp);
        return this;
    }

    /**
     * Gets vRouters from the config.
     *
     * @return Set of vRouter MAC addresses, empty is not specified,
     *         or null if not valid
     */
    public Set<MacAddress> vRouterMacs() {
        if (!object.has(VROUTER_MACS)) {
            return ImmutableSet.of();
        }

        ImmutableSet.Builder<MacAddress> builder = ImmutableSet.builder();
        ArrayNode arrayNode = (ArrayNode) object.path(VROUTER_MACS);
        for (JsonNode jsonNode : arrayNode) {
            MacAddress mac;

            String macStr = jsonNode.asText(null);
            if (macStr == null) {
                return null;
            }
            try {
                mac = MacAddress.valueOf(macStr);
            } catch (IllegalArgumentException e) {
                return null;
            }

            builder.add(mac);
        }
        return builder.build();
    }

    /**
     * Sets vRouters to the config.
     *
     * @param vRouterMacs a set of vRouter MAC addresses
     * @return this {@link SegmentRoutingAppConfig}
     */
    public SegmentRoutingAppConfig setVRouterMacs(Set<MacAddress> vRouterMacs) {
        if (vRouterMacs == null) {
            object.remove(VROUTER_MACS);
        } else {
            ArrayNode arrayNode = mapper.createArrayNode();

            vRouterMacs.forEach(mac -> {
                arrayNode.add(mac.toString());
            });

            object.set(VROUTER_MACS, arrayNode);
        }
        return this;
    }

    /**
     * Gets names of ports to which SegmentRouting does not push subnet rules.
     *
     * @return Set of port names, empty if not specified, or null
     *         if not valid
     */
    public Set<ConnectPoint> suppressSubnet() {
        if (!object.has(SUPPRESS_SUBNET)) {
            return ImmutableSet.of();
        }

        ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
        ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_SUBNET);
        for (JsonNode jsonNode : arrayNode) {
            String portName = jsonNode.asText(null);
            if (portName == null) {
                return null;
            }
            try {
                builder.add(ConnectPoint.deviceConnectPoint(portName));
            } catch (IllegalArgumentException e) {
                return null;
            }
        }
        return builder.build();
    }

    /**
     * Sets names of ports to which SegmentRouting does not push subnet rules.
     *
     * @param suppressSubnet names of ports to which SegmentRouting does not push
     *                     subnet rules
     * @return this {@link SegmentRoutingAppConfig}
     */
    public SegmentRoutingAppConfig setSuppressSubnet(Set<ConnectPoint> suppressSubnet) {
        if (suppressSubnet == null) {
            object.remove(SUPPRESS_SUBNET);
        } else {
            ArrayNode arrayNode = mapper.createArrayNode();
            suppressSubnet.forEach(connectPoint -> {
                arrayNode.add(connectPoint.deviceId() + "/" + connectPoint.port());
            });
            object.set(SUPPRESS_SUBNET, arrayNode);
        }
        return this;
    }

    /**
     * Gets connect points to which SegmentRouting does not push host rules.
     *
     * @return Set of connect points, empty if not specified, or null
     *         if not valid
     */
    public Set<ConnectPoint> suppressHostByPort() {
        if (!object.has(SUPPRESS_HOST_BY_PORT)) {
            return ImmutableSet.of();
        }

        ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
        ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_HOST_BY_PORT);
        for (JsonNode jsonNode : arrayNode) {
            String portName = jsonNode.asText(null);
            if (portName == null) {
                return null;
            }
            try {
                builder.add(ConnectPoint.deviceConnectPoint(portName));
            } catch (IllegalArgumentException e) {
                return null;
            }
        }
        return builder.build();
    }

    /**
     * Sets connect points to which SegmentRouting does not push host rules.
     *
     * @param connectPoints connect points to which SegmentRouting does not push
     *                     host rules
     * @return this {@link SegmentRoutingAppConfig}
     */
    public SegmentRoutingAppConfig setSuppressHostByPort(Set<ConnectPoint> connectPoints) {
        if (connectPoints == null) {
            object.remove(SUPPRESS_HOST_BY_PORT);
        } else {
            ArrayNode arrayNode = mapper.createArrayNode();
            connectPoints.forEach(connectPoint -> {
                arrayNode.add(connectPoint.deviceId() + "/" + connectPoint.port());
            });
            object.set(SUPPRESS_HOST_BY_PORT, arrayNode);
        }
        return this;
    }

    /**
     * Gets provider names from which SegmentRouting does not learn host info.
     *
     * @return array of provider names that need to be ignored
     */
    public Set<String> suppressHostByProvider() {
        if (!object.has(SUPPRESS_HOST_BY_PROVIDER)) {
            return ImmutableSet.of();
        }

        ImmutableSet.Builder<String> builder = ImmutableSet.builder();
        ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_HOST_BY_PROVIDER);
        for (JsonNode jsonNode : arrayNode) {
            String providerName = jsonNode.asText(null);
            if (providerName == null) {
                return null;
            }
            builder.add(providerName);
        }
        return builder.build();
    }

    /**
     * Sets provider names from which SegmentRouting does not learn host info.
     *
     * @param providers set of provider names
     * @return this {@link SegmentRoutingAppConfig}
     */
    public SegmentRoutingAppConfig setSuppressHostByProvider(Set<String> providers) {
        if (providers == null) {
            object.remove(SUPPRESS_HOST_BY_PROVIDER);
        } else {
            ArrayNode arrayNode = mapper.createArrayNode();
            providers.forEach(arrayNode::add);
            object.set(SUPPRESS_HOST_BY_PROVIDER, arrayNode);
        }
        return this;
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("vRouterMacs", vRouterMacs())
                .add("suppressSubnet", suppressSubnet())
                .add("suppressHostByPort", suppressHostByPort())
                .add("suppressHostByProvider", suppressHostByProvider())
                .add("mplsEcmp", mplsEcmp())
                .add("blackholeIps", blackholeIPs())
                .toString();
    }
}
