/*
 * Copyright 2017-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.artemis.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import org.json.JSONArray;
import org.json.JSONException;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.config.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

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

/**
 * Artemis Configuration Class.
 */
public class ArtemisConfig extends Config<ApplicationId> {
    private static final String PREFIXES = "prefixes";
    /* */
    private static final String PREFIX = "prefix";
    private static final String PATHS = "paths";
    private static final String MOAS = "moas";
    /* */
    private static final String ORIGIN = "origin";
    private static final String NEIGHBOR = "neighbor";
    private static final String ASN = "asn";
    /* */
    private static final String MONITORS = "monitors";
    /* */
    private static final String RIPE = "ripe";
    private static final String EXABGP = "exabgp";
    /* */
    private static final String MOAS_LEGIT = "legit";
    private static final String TUNNEL_POINTS = "tunnelPoints";
    private static final String TUNNEL_OVSDB_IP = "ovsdb_ip";
    private static final String TUNNEL_LOCAL_IP = "local_ip";
    private static final String TUNNEL_OVS_PORT = "ovs_port";

    private final Logger log = LoggerFactory.getLogger(getClass());

    Set<IpPrefix> prefixesToMonitor() {
        JsonNode prefixesNode = object.path(PREFIXES);
        if (!prefixesNode.isMissingNode()) {
            return Streams.stream(prefixesNode)
                    .map(prefix -> IpPrefix.valueOf(prefix.get(PREFIX).asText()))
                    .collect(Collectors.toSet());
        }
        return null;
    }

    /**
     * Gets the set of monitored prefixes with the details (prefix, paths and MOAS).
     *
     * @return artemis class prefixes
     */
    Set<ArtemisPrefixes> monitoredPrefixes() {
        Set<ArtemisPrefixes> prefixes = Sets.newHashSet();

        JsonNode prefixesNode = object.path(PREFIXES);
        if (prefixesNode.isMissingNode()) {
            log.warn("prefixes field is null!");
            return prefixes;
        }

        prefixesNode.forEach(jsonNode -> {
            IpPrefix prefix = IpPrefix.valueOf(jsonNode.get(PREFIX).asText());

            JsonNode moasNode = jsonNode.get(MOAS);
            Set<IpAddress> moasIps = Streams.stream(moasNode)
                    .map(asn -> IpAddress.valueOf(asn.asText()))
                    .collect(Collectors.toSet());

            JsonNode pathsNode = jsonNode.get(PATHS);
            Map<Integer, Map<Integer, Set<Integer>>> paths = Maps.newHashMap();
            pathsNode.forEach(path -> addPath(paths, path));

            prefixes.add(new ArtemisPrefixes(prefix, moasIps, paths));
        });

        return prefixes;
    }

    /**
     * Appends an ASN path on the ASN paths list of the Artemis application.
     *
     * @param paths active ASN paths list
     * @param path  ASN path to be added
     */
    private void addPath(Map<Integer, Map<Integer, Set<Integer>>> paths, JsonNode path) {
        Integer origin = path.path(ORIGIN).asInt();

        JsonNode firstNeighborNode = path.path(NEIGHBOR);
        // Check if neighbor exists in the configuration
        if (!firstNeighborNode.isMissingNode()) {
            firstNeighborNode.forEach(firstNeighbor -> {
                Integer firstNeighborAsn = firstNeighbor.get(ASN).asInt();

                JsonNode secondNeighborNode = firstNeighbor.path(NEIGHBOR);
                // check if second neighbor exists in configuration
                if (!secondNeighborNode.isMissingNode()) {
                    secondNeighborNode.forEach(secondNeighbor -> {
                        Integer secondNeighborAsn = secondNeighbor.asInt();

                        if (paths.containsKey(origin)) {
                            // paths already contain origin ASN.
                            Map<Integer, Set<Integer>> integerSetMap = paths.get(origin);
                            if (integerSetMap.containsKey(firstNeighborAsn)) {
                                integerSetMap.get(firstNeighborAsn).add(secondNeighborAsn);
                            } else {
                                paths.get(origin).put(firstNeighborAsn, Sets.newHashSet(secondNeighborAsn));
                            }
                        } else {
                            // origin ASN does not exist in Map.
                            Map<Integer, Set<Integer>> first2second = Maps.newHashMap();
                            first2second.put(firstNeighborAsn, Sets.newHashSet(secondNeighborAsn));
                            paths.put(origin, first2second);
                        }
                    });
                    // else append to paths without second neighbor
                } else {
                    if (!paths.containsKey(origin)) {
                        Map<Integer, Set<Integer>> first2second = Maps.newHashMap();
                        first2second.put(firstNeighborAsn, Sets.newHashSet());
                        paths.put(origin, first2second);
                    } else {
                        // paths already contain origin ASN.
                        Map<Integer, Set<Integer>> integerSetMap = paths.get(origin);
                        if (!integerSetMap.containsKey(firstNeighborAsn)) {
                            paths.get(origin).put(firstNeighborAsn, Sets.newHashSet());
                        }
                    }
                }
            });
            // else append to paths only the origin
        } else {
            if (!paths.containsKey(origin)) {
                paths.put(origin, Maps.newHashMap());
            }
        }
    }

//    /**
//     * Helper function to print the loaded ASN paths.
//     *
//     * @param paths ASN paths to print
//     */
//    private void printPaths(Map<Integer, Map<Integer, Set<Integer>>> paths) {
//        log.warn("------------------------------------");
//        paths.forEach((k, v) -> v.forEach((l, n) -> {
//            n.forEach(p -> log.warn("Origin: " + k + ", 1st: " + l + ", 2nd: " + p));
//        }));
//    }

    /**
     * Gets the active route collectors.
     *
     * @return map with type as a key and host as a value.
     */
    Map<String, Set<String>> activeMonitors() {
        Map<String, Set<String>> monitors = Maps.newHashMap();

        JsonNode monitorsNode = object.path(MONITORS);

        if (!monitorsNode.isMissingNode()) {
            JsonNode ripeNode = monitorsNode.path(RIPE);
            if (!ripeNode.isMissingNode()) {
                Set<String> hosts = Sets.newHashSet();
                ripeNode.forEach(host -> hosts.add(host.asText()));
                monitors.put(RIPE, hosts);
            }

            JsonNode exabgpNode = monitorsNode.path(EXABGP);
            if (!exabgpNode.isMissingNode()) {
                Set<String> hosts = Sets.newHashSet();
                exabgpNode.forEach(host -> hosts.add(host.asText()));
                monitors.put(EXABGP, hosts);
            }
        }

        return monitors;
    }

    /**
     * Get the information about MOAS. Including remote MOAS server IPs, OVSDB ID and local tunnel IP.
     *
     * @return MOAS information
     */
    MoasInfo moasInfo() {
        MoasInfo moasInfo = new MoasInfo();

        JsonNode moasNode = object.path(MOAS);

        if (!moasNode.isMissingNode()) {
            JsonNode legitIpsNode = moasNode.path(MOAS_LEGIT);
            if (!legitIpsNode.isMissingNode()) {
                if (legitIpsNode.isArray()) {
                    moasInfo.setMoasAddresses(
                            Streams.stream(legitIpsNode)
                                    .map(ipAddress -> IpAddress.valueOf(ipAddress.asText()))
                                    .collect(Collectors.toSet())
                    );
                } else {
                    log.warn("Legit MOAS field need to be a list");
                }
            } else {
                log.warn("No IPs for legit MOAS specified in configuration");
            }

            JsonNode tunnelPointsNode = moasNode.path(TUNNEL_POINTS);
            if (!tunnelPointsNode.isMissingNode()) {
                if (tunnelPointsNode.isArray()) {
                    tunnelPointsNode.forEach(
                            tunnelPoint -> {
                                JsonNode idNode = tunnelPoint.path(TUNNEL_OVSDB_IP),
                                        localNode = tunnelPoint.path(TUNNEL_LOCAL_IP),
                                        ovsNode = tunnelPoint.path(TUNNEL_OVS_PORT);

                                if (!idNode.isMissingNode() && !localNode.isMissingNode()) {
                                    moasInfo.addTunnelPoint(
                                            new MoasInfo.TunnelPoint(
                                                    IpAddress.valueOf(idNode.asText()),
                                                    IpAddress.valueOf(localNode.asText()),
                                                    ovsNode.asText()
                                            )
                                    );
                                } else {
                                    log.warn("Tunnel point need to have an ID and a Local IP");
                                }
                            }
                    );
                } else {
                    log.warn("Tunnel points field need to be a list");
                }
            }
        } else {
            log.warn("No tunnel points specified in configuration");
        }

        return moasInfo;
    }

    /**
     * Information holder for MOAS.
     */
    public static class MoasInfo {
        private Set<IpAddress> moasAddresses;
        private Set<TunnelPoint> tunnelPoints;

        public MoasInfo() {
            moasAddresses = Sets.newConcurrentHashSet();
            tunnelPoints = Sets.newConcurrentHashSet();
        }

        public Set<IpAddress> getMoasAddresses() {
            return moasAddresses;
        }

        public void setMoasAddresses(Set<IpAddress> moasAddresses) {
            this.moasAddresses = moasAddresses;
        }

        public Set<TunnelPoint> getTunnelPoints() {
            return tunnelPoints;
        }

        public void setTunnelPoints(Set<TunnelPoint> tunnelPoints) {
            this.tunnelPoints = tunnelPoints;
        }

        public TunnelPoint getTunnelPoint() {
            return tunnelPoints.iterator().next();
        }

        public void addTunnelPoint(TunnelPoint tunnelPoint) {
            this.tunnelPoints.add(tunnelPoint);
        }

        @Override
        public String toString() {
            return "MoasInfo{" +
                    "moasAddresses=" + moasAddresses +
                    ", tunnelPoints=" + tunnelPoints +
                    '}';
        }

        public static class TunnelPoint {
            private IpAddress ovsdbIp;
            private IpAddress localIP;
            private String ovsPort;

            public TunnelPoint(IpAddress ovsdbIp, IpAddress localIP, String ovsPort) {
                this.ovsdbIp = ovsdbIp;
                this.localIP = localIP;
                this.ovsPort = ovsPort;
            }

            public IpAddress getOvsdbIp() {
                return ovsdbIp;
            }

            public void setOvsdbIp(IpAddress ovsdbIp) {
                this.ovsdbIp = ovsdbIp;
            }

            public IpAddress getLocalIp() {
                return localIP;
            }

            public void setLocalIp(IpAddress localIP) {
                this.localIP = localIP;
            }

            public String getOvsPort() {
                return ovsPort;
            }

            public void setOvsPort(String ovsPort) {
                this.ovsPort = ovsPort;
            }

            @Override
            public String toString() {
                return "TunnelPoint{" +
                        "ovsdbIp='" + ovsdbIp + '\'' +
                        ", localIP=" + localIP +
                        ", ovsPort='" + ovsPort + '\'' +
                        '}';
            }
        }
    }

    /**
     * Configuration for a specific prefix.
     */
    public class ArtemisPrefixes {
        private IpPrefix prefix;
        private Set<IpAddress> moas;
        private Map<Integer, Map<Integer, Set<Integer>>> paths;

        ArtemisPrefixes(IpPrefix prefix, Set<IpAddress> moas, Map<Integer, Map<Integer, Set<Integer>>> paths) {
            this.prefix = checkNotNull(prefix);
            this.moas = checkNotNull(moas);
            this.paths = checkNotNull(paths);
        }

        protected IpPrefix prefix() {
            return prefix;
        }

        protected Set<IpAddress> moas() {
            return moas;
        }

        protected Map<Integer, Map<Integer, Set<Integer>>> paths() {
            return paths;
        }

        /**
         * Given a path we check if the origin is a friendly MOAS or our ASN.
         * If the origin ASN is not ours the we have a hijack of type 0. Next, in case that the first neighbor is
         * not a legit neighbor from our configuration we detect a hijack of type 1 and lastly, if the second
         * neighbor is not a legit neighbor we detect a type 2 hijack.
         *
         * @param path as-path that announces our prefix and found from monitors
         * @return <code>0</code> no bgp hijack detected
         * <code>50</code> friendly anycaster announcing our prefix
         * <code>100+i</code> BGP hijack type i (0 &lt;= i &lt;=2)
         */
        int checkPath(JSONArray path) {
            // TODO add MOAS check
            ArrayList<Integer> asnPath = new ArrayList<>();
            for (int i = 0; i < path.length(); i++) {
                try {
                    asnPath.add(path.getInt(i));
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            // reverse the list to get path starting from origin
            Collections.reverse(asnPath);

            if (asnPath.size() > 0 && !paths.containsKey(asnPath.get(0))) {
                return 100;
            } else if (asnPath.size() > 1 && !paths.get(asnPath.get(0)).containsKey(asnPath.get(1))) {
                return 101;
            } else if (asnPath.size() > 2 && !paths.get(asnPath.get(0)).get(asnPath.get(1)).contains(asnPath.get(2))) {
                return 102;
            }
            return 0;
        }

        @Override
        public String toString() {
            return "ArtemisPrefixes{" +
                    "prefix=" + prefix +
                    ", moas=" + moas +
                    ", paths=" + paths +
                    '}';
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(prefix);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj instanceof PrefixHandler) {
                final PrefixHandler that = (PrefixHandler) obj;
                return Objects.equals(this.prefix, that.getPrefix());
            }
            return false;
        }
    }

}
