/*
 * Copyright 2015 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.onosproject.routing.config;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Sets;
import org.onlab.packet.IpAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.Config;

import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Configuration object for BGP config.
 */
public class BgpConfig extends Config<ApplicationId> {

    public static final String SPEAKERS = "bgpSpeakers";
    public static final String CONNECT_POINT = "connectPoint";
    public static final String NAME = "name";
    public static final String PEERS = "peers";
    public static final String VLAN = "vlan";

    /**
     * Gets the set of configured BGP speakers.
     *
     * @return BGP speakers
     */
    public Set<BgpSpeakerConfig> bgpSpeakers() {
        Set<BgpSpeakerConfig> speakers = Sets.newHashSet();

        JsonNode speakersNode = object.get(SPEAKERS);

        if (speakersNode == null) {
            return speakers;
        }

        speakersNode.forEach(jsonNode -> {
            Set<IpAddress> listenAddresses = Sets.newHashSet();
            jsonNode.path(PEERS).forEach(addressNode ->
                            listenAddresses.add(IpAddress.valueOf(addressNode.asText()))
            );

            Optional<String> name;
            if (jsonNode.get(NAME) == null) {
                name = Optional.empty();
            } else {
                name = Optional.of(jsonNode.get(NAME).asText());
            }

            VlanId vlan = getVlan(jsonNode);

            speakers.add(new BgpSpeakerConfig(name,
                    vlan,
                    ConnectPoint.deviceConnectPoint(jsonNode.path(CONNECT_POINT).asText()),
                    listenAddresses));
        });

        return speakers;
    }

    // If configured, it retreives a VLAN Id from a BGP speaker node
    private VlanId getVlan(JsonNode node) {
        VlanId vlan = VlanId.NONE;
        if (!node.path(VLAN).isMissingNode()) {
            vlan = VlanId.vlanId(node.path(VLAN).asText());
        }
        return vlan;
    }

    /**
     * Examines whether a name of BGP speaker exists in configuration.
     *
     * @param name name of BGP speaker being search
     * @return speaker
     */
    public BgpSpeakerConfig getSpeakerWithName(String name) {
        for (BgpConfig.BgpSpeakerConfig speaker : bgpSpeakers()) {
            if (speaker.name().filter(name::equals).isPresent()) {
                return speaker;
            }
        }
        return null;
    }

    /**
     * Adds BGP speaker to configuration.
     *
     * @param speaker BGP speaker configuration entry
     */
    public void addSpeaker(BgpSpeakerConfig speaker) {
        ObjectNode speakerNode = JsonNodeFactory.instance.objectNode();

        speakerNode.put(NAME, speaker.name().get());

        speakerNode.put(VLAN, speaker.vlan().toString());

        speakerNode.put(CONNECT_POINT, speaker.connectPoint().elementId().toString()
                + "/" + speaker.connectPoint().port().toString());

        ArrayNode peersNode = speakerNode.putArray(PEERS);
        for (IpAddress peerAddress: speaker.peers()) {
            peersNode.add(peerAddress.toString());
        }

        ArrayNode speakersArray = bgpSpeakers().isEmpty() ?
                initBgpConfiguration() : (ArrayNode) object.get(SPEAKERS);
        speakersArray.add(speakerNode);
    }

    /**
     * Removes BGP speaker from configuration.
     *
     * @param speakerName BGP speaker name
     */
    public void removeSpeaker(String speakerName) {
        ArrayNode speakersArray = (ArrayNode) object.get(SPEAKERS);

        for (int i = 0; i < speakersArray.size(); i++) {
            if (speakersArray.get(i).hasNonNull(NAME) &&
                    speakersArray.get(i).get(NAME).asText().equals(speakerName)) {
                speakersArray.remove(i);
                return;
            }
        }
    }

    /**
     * Adds peering address to BGP speaker.
     *
     * @param speakerName name of BGP speaker
     * @param peerAddress peering address to be added
     */
    public void addPeerToSpeaker(String speakerName, IpAddress peerAddress) {
        JsonNode speakersNode = object.get(SPEAKERS);
        speakersNode.forEach(jsonNode -> {
            if (jsonNode.hasNonNull(NAME) &&
                    jsonNode.get(NAME).asText().equals(speakerName)) {
                ArrayNode peersNode = (ArrayNode) jsonNode.get(PEERS);
                for (int i = 0; i < peersNode.size(); i++) {
                    if (peersNode.get(i).asText().equals(peerAddress.toString())) {
                        return; // Peer already exists.
                    }
                }
                peersNode.add(peerAddress.toString());
            }
        });
    }

    /**
     * Finds BGP speaker peering with a given external peer.
     *
     * @param peerAddress BGP peer address
     * @return BGP speaker
     */
    public BgpSpeakerConfig getSpeakerFromPeer(IpAddress peerAddress) {
        for (BgpConfig.BgpSpeakerConfig speaker : bgpSpeakers()) {
            if (speaker.peers().contains(peerAddress)) {
                return speaker;
            }
        }
        return null;
    }

    /**
     * Removes peering address from BGP speaker.
     *
     * @param speaker BGP speaker configuration entries
     * @param peerAddress peering address to be removed
     */
    public void removePeerFromSpeaker(BgpSpeakerConfig speaker, IpAddress peerAddress) {
        JsonNode speakersNode = object.get(SPEAKERS);
        speakersNode.forEach(jsonNode -> {
            if (jsonNode.hasNonNull(NAME) &&
                    jsonNode.get(NAME).asText().equals(speaker.name().get())) {
                ArrayNode peersNode = (ArrayNode) jsonNode.get(PEERS);
                for (int i = 0; i < peersNode.size(); i++) {
                    if (peersNode.get(i).asText().equals(peerAddress.toString())) {
                        peersNode.remove(i);
                        return;
                    }
                }
            }
        });
    }

    /**
     * Creates empty configuration for BGP speakers.
     *
     * @return empty array of BGP speakers
     */
    private ArrayNode initBgpConfiguration() {
        return object.putArray(SPEAKERS);
    }


    /**
     * Configuration for a BGP speaker.
     */
    public static class BgpSpeakerConfig {

        private Optional<String> name;
        private VlanId vlanId;
        private ConnectPoint connectPoint;
        private Set<IpAddress> peers;

        public BgpSpeakerConfig(Optional<String> name, VlanId vlanId,
                                ConnectPoint connectPoint, Set<IpAddress> peers) {
            this.name = checkNotNull(name);
            this.vlanId = checkNotNull(vlanId);
            this.connectPoint = checkNotNull(connectPoint);
            this.peers = checkNotNull(peers);
        }

        public Optional<String> name() {
            return name;
        }

        public VlanId vlan() {
            return vlanId;
        }

        public ConnectPoint connectPoint() {
            return connectPoint;
        }

        public Set<IpAddress> peers() {
            return peers;
        }

        /**
         * Examines if BGP peer is connected.
         *
         * @param peer IP address of peer
         * @return result of search
         */
        public boolean isConnectedToPeer(IpAddress peer) {
            for (final IpAddress entry : peers()) {
                if (entry.equals(peer)) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj instanceof BgpSpeakerConfig) {
                final BgpSpeakerConfig that = (BgpSpeakerConfig) obj;
                return Objects.equals(this.name, that.name) &&
                        Objects.equals(this.vlanId, that.vlanId) &&
                        Objects.equals(this.connectPoint, that.connectPoint) &&
                        Objects.equals(this.peers, that.peers);
            }
            return false;
        }

        @Override
        public int hashCode() {
            return Objects.hash(name, vlanId, connectPoint, peers);
        }
    }
}
