/*
 * Copyright 2014-2017 Real Logic Ltd.
 *
 * 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 io.aeron.driver.status;

import org.agrona.collections.MutableInteger;
import org.agrona.concurrent.status.CountersReader;
import org.agrona.concurrent.status.StatusIndicator;
import org.agrona.concurrent.status.StatusIndicatorReader;
import org.agrona.concurrent.status.UnsafeBufferStatusIndicator;

/**
 * Utilities for applications to use to help with counters.
 */
public class StatusUtil
{
    /**
     * Return the controllable idle strategy {@link StatusIndicator}.
     *
     * @param countersReader that holds the status indicator.
     * @return status indicator to use or null if not found.
     */
    public static StatusIndicator controllableIdleStrategy(final CountersReader countersReader)
    {
        final MutableInteger id = new MutableInteger();
        StatusIndicator statusIndicator = null;

        id.value = -1;

        countersReader.forEach(
            (counterId, typeId, keyBuffer, label) ->
            {
                if (counterId == SystemCounterDescriptor.CONTROLLABLE_IDLE_STRATEGY.id() &&
                    label.equals(SystemCounterDescriptor.CONTROLLABLE_IDLE_STRATEGY.label()))
                {
                    id.value = counterId;
                }
            });

        if (-1 != id.value)
        {
            statusIndicator = new UnsafeBufferStatusIndicator(countersReader.valuesBuffer(), id.value);
        }

        return statusIndicator;
    }

    /**
     * Return the read-only status indicator for the given send channel URI.
     *
     * @see ChannelEndpointStatus for status values and indications.
     *
     * @param countersReader that holds the status indicator.
     * @param uri for the send channel.
     * @return read-only status indicator that can be used to query the status of the send channel or null
     */
    public static StatusIndicatorReader sendChannelStatus(final CountersReader countersReader, final String uri)
    {
        final MutableInteger id = new MutableInteger();
        StatusIndicatorReader statusReader = null;

        id.value = -1;

        countersReader.forEach(
            (counterId, typeId, keyBuffer, label) ->
            {
                if (typeId == SendChannelStatus.SEND_CHANNEL_STATUS_TYPE_ID)
                {
                    final String bufferUri = keyBuffer.getStringAscii(ChannelEndpointStatus.CHANNEL_OFFSET);

                    if (uri.equals(bufferUri))
                    {
                        id.value = counterId;
                    }
                }
            });

        if (-1 != id.value)
        {
            statusReader = new UnsafeBufferStatusIndicator(countersReader.valuesBuffer(), id.value);
        }

        return statusReader;
    }

    /**
     * Return the read-only status indicator for the given receive channel URI.
     *
     * @see ChannelEndpointStatus for status values and indications.
     *
     * @param countersReader that holds the status indicator.
     * @param uri for the receive channel.
     * @return read-only status indicator that can be used to query the status of the receive channel or null.
     */
    public static StatusIndicatorReader receiveChannelStatus(final CountersReader countersReader, final String uri)
    {
        final MutableInteger id = new MutableInteger();
        StatusIndicatorReader statusReader = null;

        id.value = -1;

        countersReader.forEach(
            (counterId, typeId, keyBuffer, label) ->
            {
                if (typeId == ReceiveChannelStatus.RECEIVE_CHANNEL_STATUS_TYPE_ID)
                {
                    final String bufferUri = keyBuffer.getStringAscii(ChannelEndpointStatus.CHANNEL_OFFSET);

                    if (uri.equals(bufferUri))
                    {
                        id.value = counterId;
                    }
                }
            });

        if (-1 != id.value)
        {
            statusReader = new UnsafeBufferStatusIndicator(countersReader.valuesBuffer(), id.value);
        }

        return statusReader;
    }
}

@@ -913,54 +913,41 @@
 %0A * 
-Utilities for applications to use to help with
+Functions for working with status
  cou
@@ -1305,64 +1305,8 @@
   %7B%0A
-        final MutableInteger id = new MutableInteger();%0A
     
@@ -1345,33 +1345,32 @@
 tor = null;%0A
-%0A
         
 id.value = -
@@ -1353,37 +1353,72 @@
 ll;%0A        
-id.value = 
+final MutableInteger id = new MutableInteger(
 -1
+)
 ;%0A%0A        c
@@ -2076,84 +2076,8 @@
   *%0A
-     * @see ChannelEndpointStatus for status values and indications.%0A     *%0A
     
@@ -2140,35 +2140,46 @@
 .%0A     * @param 
-uri
+channel       
  for the send ch
@@ -2292,16 +2292,85 @@
 or null%0A
+     * @see ChannelEndpointStatus for status values and indications.%0A
      */%0A
@@ -2473,35 +2473,39 @@
 inal String 
-uri
+channel
 )%0A    %7B%0A
         fina
@@ -2496,64 +2496,8 @@
   %7B%0A
-        final MutableInteger id = new MutableInteger();%0A
     
@@ -2539,33 +2539,32 @@
 der = null;%0A
-%0A
         
 id.value = -
@@ -2547,37 +2547,72 @@
 ll;%0A        
-id.value = 
+final MutableInteger id = new MutableInteger(
 -1
+)
 ;%0A%0A        c
@@ -2820,33 +2820,31 @@
     
-final String bufferUri = 
+if (channel.startsWith(
 keyB
@@ -2905,55 +2905,8 @@
 SET)
-;%0A%0A                    if (uri.equals(bufferUri
 ))%0A 
@@ -3314,84 +3314,8 @@
   *%0A
-     * @see ChannelEndpointStatus for status values and indications.%0A     *%0A
     
@@ -3386,19 +3386,30 @@
  @param 
-uri
+channel       
  for the
@@ -3537,16 +3537,85 @@
 r null.%0A
+     * @see ChannelEndpointStatus for status values and indications.%0A
      */%0A
@@ -3729,19 +3729,23 @@
 ing 
-uri
+channel
 )%0A    %7B%0A
     
@@ -3744,64 +3744,8 @@
   %7B%0A
-        final MutableInteger id = new MutableInteger();%0A
     
@@ -3791,25 +3791,24 @@
 = null;%0A
-%0A
         
 id.value
@@ -3803,21 +3803,56 @@
     
-id.value = 
+final MutableInteger id = new MutableInteger(
 -1
+)
 ;%0A%0A 
@@ -4074,33 +4074,31 @@
     
-final String bufferUri = 
+if (channel.startsWith(
 keyB
@@ -4159,55 +4159,8 @@
 SET)
-;%0A%0A                    if (uri.equals(bufferUri
 ))%0A 

Deal with case of truncated key stored for status counter.