/*
 * 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.ignite.internal.client;

import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.ignite.internal.client.util.GridClientConsistentHash;
import org.apache.ignite.internal.client.util.GridClientUtils;
import org.apache.ignite.internal.util.typedef.internal.U;

/**
 * Affinity function for partitioned cache. This function supports the following
 * configuration:
 * <ul>
 * <li>
 *      {@code backupFilter} - Optional filter for back up nodes. If provided, then only
 *      nodes that pass this filter will be selected as backup nodes and only nodes that
 *      don't pass this filter will be selected as primary nodes. If not provided, then
 *      primary and backup nodes will be selected out of all nodes available for this cache.
 *      <p>
 *      NOTE: In situations where there are no primary nodes at all, i.e. no nodes for which backup
 *      filter returns {@code false}, first backup node for the key will be considered primary.
 * </li>
 * </ul>
*/
@SuppressWarnings("NullableProblems")
public class GridClientPartitionAffinity implements GridClientDataAffinity, GridClientTopologyListener {
    /**
     * This resolver is used to provide alternate hash ID, other than node ID.
     * <p>
     * Node IDs constantly change when nodes get restarted, which causes them to
     * be placed on different locations in the hash ring, and hence causing
     * repartitioning. Providing an alternate hash ID, which survives node restarts,
     * puts node on the same location on the hash ring, hence minimizing required
     * repartitioning.
     */
    @SuppressWarnings("PublicInnerClass")
    public static interface HashIdResolver {
        /**
         * Gets alternate hash ID, other than node ID.
         *
         * @param node Node.
         * @return Hash ID.
         */
        public Object getHashId(GridClientNode node);
    }

    /** Default number of partitions. */
    public static final int DFLT_PARTITION_CNT = 10000;

    /** Node hash. */
    private final GridClientConsistentHash<NodeInfo> nodeHash;

    /** Hash id resolver. */
    private HashIdResolver hashIdRslvr = new HashIdResolver() {
        @Override public Object getHashId(GridClientNode node) {
            return node.consistentId();
        }
    };

    /** Total number of partitions. */
    private int parts = DFLT_PARTITION_CNT;

    /** Cached added node infos. */
    private final ConcurrentMap<UUID, NodeInfo> addedNodes = new ConcurrentHashMap<>();

    /** Optional backup filter. */
    private GridClientPredicate<UUID> backupFilter;

    /** Optional backup filter. */
    private final GridClientPredicate<NodeInfo> backupIdFilter =new GridClientPredicate<NodeInfo>() {
        @Override public boolean apply(NodeInfo info) {
            return backupFilter == null || backupFilter.apply(info.nodeId());
        }
    };

    /** Optional primary filter. */
    private final GridClientPredicate<NodeInfo> primaryIdFilter = new GridClientPredicate<NodeInfo>() {
        @Override public boolean apply(NodeInfo info) {
            return backupFilter == null || !backupFilter.apply(info.nodeId());
        }
    };

    /**
     * Empty constructor with all defaults.
     */
    public GridClientPartitionAffinity() {
        this(null, null);
    }

    /**
     * Initializes optional counts for replicas and backups.
     * <p>
     * Note that {@code excludeNeighbors} parameter is ignored if {@code backupFilter} is set.
     *
     * @param parts Total number of partitions. If {@code null} than {@link #DFLT_PARTITION_CNT} will be used.
     * @param backupFilter Optional back up filter for nodes. If provided, then primary nodes
     *      will be selected from all nodes outside of this filter, and backups will be selected
     *      from all nodes inside it.
     */
    public GridClientPartitionAffinity(Integer parts, GridClientPredicate<UUID> backupFilter) {
        this.parts = parts == null ? DFLT_PARTITION_CNT : parts;
        this.backupFilter = backupFilter;

        nodeHash = new GridClientConsistentHash<>();
    }

    /**
     * Gets total number of key partitions. To ensure that all partitions are
     * equally distributed across all nodes, please make sure that this
     * number is significantly larger than a number of nodes. Also, partition
     * size should be relatively small. Try to avoid having partitions with more
     * than quarter million keys.
     * <p>
     * Note that for fully replicated caches this method should always
     * return {@code 1}.
     *
     * @return Total partition count.
     */
    public int getPartitions() {
        return parts;
    }

    /**
     * Sets total number of partitions.
     *
     * @param parts Total number of partitions.
     * @return {@code this} for chaining.
     */
    public GridClientPartitionAffinity setPartitions(int parts) {
        this.parts = parts;

        return this;
    }

    /**
     * Gets hash ID resolver for nodes. This resolver is used to provide
     * alternate hash ID, other than node ID.
     * <p>
     * Node IDs constantly change when nodes get restarted, which causes them to
     * be placed on different locations in the hash ring, and hence causing
     * repartitioning. Providing an alternate hash ID, which survives node restarts,
     * puts node on the same location on the hash ring, hence minimizing required
     * repartitioning.
     *
     * @return Hash ID resolver.
     */
    public HashIdResolver getHashIdResolver() {
        return hashIdRslvr;
    }

    /**
     * Sets hash ID resolver for nodes. This resolver is used to provide
     * alternate hash ID, other than node ID.
     * <p>
     * Node IDs constantly change when nodes get restarted, which causes them to
     * be placed on different locations in the hash ring, and hence causing
     * repartitioning. Providing an alternate hash ID, which survives node restarts,
     * puts node on the same location on the hash ring, hence minimizing required
     * repartitioning.
     *
     * @param hashIdRslvr Hash ID resolver.
     * @return {@code this} for chaining.
     */
    public GridClientPartitionAffinity setHashIdResolver(HashIdResolver hashIdRslvr) {
        this.hashIdRslvr = hashIdRslvr;

        return this;
    }

    /**
     * Gets optional backup filter. If not {@code null}, then primary nodes will be
     * selected from all nodes outside of this filter, and backups will be selected
     * from all nodes inside it.
     * <p>
     * Note that {@code excludeNeighbors} parameter is ignored if {@code backupFilter} is set.
     *
     * @return Optional backup filter.
     */
    public GridClientPredicate<UUID> getBackupFilter() {
        return backupFilter;
    }

    /**
     * Sets optional backup filter. If provided, then primary nodes will be selected
     * from all nodes outside of this filter, and backups will be selected from all
     * nodes inside it.
     * <p>
     * Note that {@code excludeNeighbors} parameter is ignored if {@code backupFilter} is set.
     *
     * @param backupFilter Optional backup filter.
     * @return {@code this} for chaining.
     */
    public GridClientPartitionAffinity setBackupFilter(GridClientPredicate<UUID> backupFilter) {
        this.backupFilter = backupFilter;

        return this;
    }

    /** {@inheritDoc} */
    @Override public GridClientNode node(Object key, Collection<? extends GridClientNode> nodes) {
        if (nodes == null || nodes.isEmpty())
            return null;

        if (nodes.size() == 1) // Minor optimization.
            return GridClientUtils.first(nodes);

        final Map<NodeInfo, GridClientNode> lookup = U.newHashMap(nodes.size());

        // Store nodes in map for fast lookup.
        for (GridClientNode node : nodes)
            // Get node info and update consistent hash, if required.
            lookup.put(resolveNodeInfo(node), node);

        final Collection<NodeInfo> nodeInfos = lookup.keySet();

        NodeInfo nodeInfo;
        int part = partition(key);

        if (backupFilter == null)
            nodeInfo = nodeHash.node(part, nodeInfos);
        else {
            nodeInfo = nodeHash.node(part, primaryIdFilter, GridClientUtils.contains(nodeInfos));

            if (nodeInfo == null)
                // Select from backup nodes.
                nodeInfo = nodeHash.node(part, backupIdFilter, GridClientUtils.contains(nodeInfos));
        }

        return lookup.get(nodeInfo);
    }

    /** {@inheritDoc} */
    private int partition(Object key) {
        return Math.abs(key.hashCode() % getPartitions());
    }

    /** {@inheritDoc} */
    @Override public void onNodeAdded(GridClientNode node) {
        // No-op.
    }

    /** {@inheritDoc} */
    @Override public void onNodeRemoved(GridClientNode node) {
        UUID nodeId = node.nodeId();
        NodeInfo nodeInfo = addedNodes.remove(nodeId);

        if (nodeInfo == null)
            return;

        nodeHash.removeNode(nodeInfo);
    }

    /**
     * Resolve node info for specified node.
     * Add node to hash circle if this is the first node invocation.
     *
     * @param n Node to get info for.
     * @return Node info.
     */
    private NodeInfo resolveNodeInfo(GridClientNode n) {
        UUID nodeId = n.nodeId();
        NodeInfo nodeInfo = addedNodes.get(nodeId);

        if (nodeInfo != null)
            return nodeInfo;

        nodeInfo = new NodeInfo(nodeId, hashIdRslvr == null ? nodeId : hashIdRslvr.getHashId(n));

        addedNodes.put(nodeId, nodeInfo);
        nodeHash.addNode(nodeInfo, 1);

        return nodeInfo;
    }

    /** {@inheritDoc} */
    @Override public String toString() {
        StringBuilder sb = new StringBuilder(getClass().getSimpleName());

        sb.append(" [nodeHash=").append(nodeHash).
            append(", hashIdRslvr=").append(hashIdRslvr).
            append(", parts=").append(parts).
            append(", addedNodes=").append(addedNodes).
            append(", backupFilter=").append(backupFilter).append("]");

        return sb.toString();
    }

    /**
     * Node hash ID.
     */
    private static final class NodeInfo implements Comparable<NodeInfo> {
        /** Node ID. */
        private final UUID nodeId;

        /** Hash ID. */
        private final Object hashId;

        /**
         * @param nodeId Node ID.
         * @param hashId Hash ID.
         */
        private NodeInfo(UUID nodeId, Object hashId) {
            assert nodeId != null;
            assert hashId != null;

            this.hashId = hashId;
            this.nodeId = nodeId;
        }

        /**
         * @return Node ID.
         */
        public UUID nodeId() {
            return nodeId;
        }

        /**
         * @return Hash ID.
         */
        public Object hashId() {
            return hashId;
        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return hashId.hashCode();
        }

        /** {@inheritDoc} */
        @Override public boolean equals(Object obj) {
            if (!(obj instanceof NodeInfo))
                return false;

            NodeInfo that = (NodeInfo)obj;

            // If objects are equal, hash codes should be the same.
            // Cannot use that.hashId.equals(hashId) due to Comparable<N> interface restrictions.
            return that.nodeId.equals(nodeId) && that.hashCode() == hashCode();
        }

        /** {@inheritDoc} */
        @Override public int compareTo(NodeInfo o) {
            int diff = nodeId.compareTo(o.nodeId);

            if (diff == 0)
                diff = Integer.compare(hashCode(), o.hashCode());

            return diff;
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return NodeInfo.class.getSimpleName() +
                " [nodeId=" + nodeId +
                ", hashId=" + hashId + ']';
        }
    }
}