/*
 * Copyright 2015 jonathan.colt.
 *
 * 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 com.jivesoftware.os.amza.client.http;

import com.google.common.collect.Maps;
import com.jivesoftware.os.amza.api.ring.RingMember;
import com.jivesoftware.os.amza.api.ring.RingMemberAndHost;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 *
 * @author jonathan.colt
 */
public class Ring {

    private static final Random RANDOM = new Random(); // Random number generator
    private final int leaderIndex;
    final RingMemberAndHost[] members;

    public Ring(int leaderIndex, RingMemberAndHost[] members) {
        this.leaderIndex = leaderIndex;
        this.members = members;
    }

    public RingMemberAndHost leader() {
        return (leaderIndex == -1) ? null : members[leaderIndex];
    }

    public RingMemberAndHost[] actualRing() {
        return members;
    }

    public RingMemberAndHost[] orderedRing(List<RingMember> membersInOrder) {
        Map<RingMember, RingMemberAndHost> memberHosts = Maps.uniqueIndex(Arrays.asList(members),
            (input) -> input.ringMember);
        RingMemberAndHost[] ordered = new RingMemberAndHost[membersInOrder.size()];
        for (int i = 0; i < membersInOrder.size(); i++) {
            ordered[i] = memberHosts.get(membersInOrder.get(i));
        }
        return ordered;
    }

    public RingMemberAndHost[] leaderlessRing() {
        if (leaderIndex == -1) {
            return Arrays.copyOf(members, members.length);
        } else {
            RingMemberAndHost[] memberAndHosts = new RingMemberAndHost[members.length - 1];
            System.arraycopy(members, 0, memberAndHosts, 0, leaderIndex);
            System.arraycopy(members, leaderIndex + 1, memberAndHosts, leaderIndex, members.length - 1 - leaderIndex);
            return memberAndHosts;
        }
    }

    public RingMemberAndHost[] randomizeRing() {
        RingMemberAndHost[] array = Arrays.copyOf(members, members.length);
        for (int i = 0; i < array.length; i++) {
            int randomPosition = RANDOM.nextInt(array.length);
            RingMemberAndHost temp = array[i];
            array[i] = array[randomPosition];
            array[randomPosition] = temp;
        }
        return array;
    }

}

@@ -639,16 +639,56 @@
 .http;%0A%0A
+import com.google.common.collect.Lists;%0A
 import c
@@ -1692,32 +1692,37 @@
 ember);%0A        
+List%3C
 RingMemberAndHos
@@ -1714,34 +1714,33 @@
 ingMemberAndHost
-%5B%5D
+%3E
  ordered = new R
@@ -1738,108 +1738,234 @@
 d = 
-new RingMemberAndHost%5BmembersInOrder.size()%5D;%0A        for (int i = 0; i %3C membersInOrder.size(); i++
+Lists.newArrayListWithCapacity(members.length);%0A        for (RingMember ringMember : membersInOrder) %7B%0A            RingMemberAndHost ringMemberAndHost = memberHosts.remove(ringMember);%0A            if (ringMemberAndHost != null
 ) %7B%0A
@@ -1980,58 +1980,184 @@
     
+   
+ 
 ordered
-%5Bi%5D = m
+.add(ringMemberAndHost);%0A            %7D%0A        %7D%0A        for (RingM
 ember
+And
 Host
-s.get(membersInOrder.get(i)
+ ringMemberAndHost : memberHosts.values()) %7B%0A            ordered.add(ringMemberAndHost
 );%0A 
@@ -2187,16 +2187,50 @@
  ordered
+.toArray(new RingMemberAndHost%5B0%5D)
 ;%0A    %7D%0A

fix ordered ring cold start in client takeFromTransactionId