/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.cassandra.hadoop.cql3;

import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.HostDistance;
import com.datastax.driver.core.Statement;
import com.datastax.driver.core.policies.LoadBalancingPolicy;
import com.google.common.base.Function;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * This load balancing policy is intended to be used only for CqlRecordReader when it fetches a particular split.
 * <p/>
 * It chooses alive hosts only from the set of the given replicas - because the connection is used to load the data from
 * the particular split, with a strictly defined list of the replicas, it is pointless to try the other nodes.
 * The policy tracks which of the replicas are alive, and when a new query plan is requested, it returns those replicas
 * in the following order:
 * <ul>
 * <li>the local node</li>
 * <li>the collection of the remaining hosts (which is shuffled on each request)</li>
 * </ul>
 */
class LimitedLocalNodeFirstLocalBalancingPolicy implements LoadBalancingPolicy
{
    private final static Logger logger = LoggerFactory.getLogger(LimitedLocalNodeFirstLocalBalancingPolicy.class);

    private final static Set<InetAddress> localAddresses = Collections.unmodifiableSet(getLocalInetAddresses());

    private final CopyOnWriteArraySet<Host> liveReplicaHosts = new CopyOnWriteArraySet<>();

    private final Set<InetAddress> replicaAddresses = new HashSet<>();

    public LimitedLocalNodeFirstLocalBalancingPolicy(String[] replicas)
    {
        for (String replica : replicas)
        {
            try
            {
                InetAddress[] addresses = InetAddress.getAllByName(replica);
                Collections.addAll(replicaAddresses, addresses);
            }
            catch (UnknownHostException e)
            {
                logger.warn("Invalid replica host name: {}, skipping it", replica);
            }
        }
        logger.trace("Created instance with the following replicas: {}", Arrays.asList(replicas));
    }

    @Override
    public void init(Cluster cluster, Collection<Host> hosts)
    {
        List<Host> replicaHosts = new ArrayList<>();
        for (Host host : hosts)
        {
            if (replicaAddresses.contains(host.getAddress()))
            {
                replicaHosts.add(host);
            }
        }
        liveReplicaHosts.addAll(replicaHosts);
        logger.trace("Initialized with replica hosts: {}", replicaHosts);
    }

    @Override
    public void close()
    {
        //
    }

    @Override
    public HostDistance distance(Host host)
    {
        if (isLocalHost(host))
        {
            return HostDistance.LOCAL;
        }
        else
        {
            return HostDistance.REMOTE;
        }
    }

    @Override
    public Iterator<Host> newQueryPlan(String keyspace, Statement statement)
    {
        List<Host> local = new ArrayList<>(1);
        List<Host> remote = new ArrayList<>(liveReplicaHosts.size());
        for (Host liveReplicaHost : liveReplicaHosts)
        {
            if (isLocalHost(liveReplicaHost))
            {
                local.add(liveReplicaHost);
            }
            else
            {
                remote.add(liveReplicaHost);
            }
        }

        Collections.shuffle(remote);

        logger.trace("Using the following hosts order for the new query plan: {} | {}", local, remote);

        return Iterators.concat(local.iterator(), remote.iterator());
    }

    @Override
    public void onAdd(Host host)
    {
        if (replicaAddresses.contains(host.getAddress()))
        {
            liveReplicaHosts.add(host);
            logger.trace("Added a new host {}", host);
        }
    }

    @Override
    public void onUp(Host host)
    {
        if (replicaAddresses.contains(host.getAddress()))
        {
            liveReplicaHosts.add(host);
            logger.trace("The host {} is now up", host);
        }
    }

    @Override
    public void onDown(Host host)
    {
        if (liveReplicaHosts.remove(host))
        {
            logger.trace("The host {} is now down", host);
        }
    }


    @Override
    public void onRemove(Host host)
    {
        if (liveReplicaHosts.remove(host))
        {
            logger.trace("Removed the host {}", host);
        }
    }

    public void onSuspected(Host host)
    {
        // not supported by this load balancing policy
    }

    private static boolean isLocalHost(Host host)
    {
        InetAddress hostAddress = host.getAddress();
        return hostAddress.isLoopbackAddress() || localAddresses.contains(hostAddress);
    }

    private static Set<InetAddress> getLocalInetAddresses()
    {
        try
        {
            return Sets.newHashSet(Iterators.concat(
                    Iterators.transform(
                            Iterators.forEnumeration(NetworkInterface.getNetworkInterfaces()),
                            new Function<NetworkInterface, Iterator<InetAddress>>()
                            {
                                @Override
                                public Iterator<InetAddress> apply(NetworkInterface netIface)
                                {
                                    return Iterators.forEnumeration(netIface.getInetAddresses());
                                }
                            })));
        }
        catch (SocketException e)
        {
            logger.warn("Could not retrieve local network interfaces.", e);
            return Collections.emptySet();
        }
    }
}
