content: /*
   * Copyright (C) 2015 AChep@xda <artemchep@gmail.com>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   * MA  02110-1301, USA.
   */
  package com.achep.base.notifications;
  
  import android.annotation.SuppressLint;
  import android.os.SystemClock;
  import androidx.annotation.NonNull;
  
  import com.achep.base.Device;
  
  import java.util.ArrayList;
  
  import timber.log.Timber;
  
  import static com.achep.base.Build.DEBUG;
  
  /**
   * A helper class to help to not mess up with ids of notifications.
   *
   * @author Artem Chepurnoy
   */
  public class NotificationSpace {
  
      private static final String TAG = "NotificationSpace";
  
      private static NotificationSpace sInstance;
  
      @NonNull
      private final ArrayList<Integer> mList = new ArrayList<>();
  
      @NonNull
      public static synchronized NotificationSpace getInstance() {
          if (sInstance == null) {
              sInstance = new NotificationSpace();
          }
          return sInstance;
      }
  
      public void requestRange(int from, int to) {
          int i = 0;
          int length = mList.size();
          for (; i < length; i++) {
              if (mList.get(i) >= from) {
                  //noinspection CaughtExceptionImmediatelyRethrown
                  try {
                      int a = mList.get(i);
                      if (to >= a) throw new RuntimeException();
                  } catch (Exception e) {
                      if (DEBUG) {
                          throw e;
                      } else Timber.tag(TAG).e(e.getMessage());
                  }
                  break;
              }
          }
          // Add a new range.
          mList.add(i, to);
          mList.add(i, from);
      }
  
      /**
       * You must call this method before creating a new notification to
       * ensure that you don't mess with ids.
       */
      public void ensure(int id) {
          final int length = mList.size();
          for (int i = 0; i < length; i += 2) {
              if (mList.get(i) <= id && mList.get(i + 1) >= id) return;
          }
          // Oh no
          throw new RuntimeException(
                  "You must request range before:"
                          + " id=" + id
                          + " list=" + mList.toString());
      }
  
      /**
       * @return the string which is granted to be unique among other ids
       * generated by this method.
       */
      public static String generateUniqueTag() {
          final long a = nanoTime();
          //noinspection StatementWithEmptyBody
          while (nanoTime() == a) ; // just to be sure
          // on the other side, converting long to string
          // will probably always last more than 0 ns.
          return Long.toString(nanoTime());
      }
  
      @SuppressLint("NewApi")
      private static long nanoTime() {
          return Device.hasJellyBeanMR1Api()
                  ? SystemClock.elapsedRealtimeNanos()
                  : System.nanoTime();
      }
  
  }
  