static int nextIndex(int index, int size) {
    if (size <= 1) {
      return -1;
    }
    // TODO: refactor, simplify
    int i = index + 1;            // switch to 1-based
    if (isMinLevel(index)) {      // we are at min level
      if ((i & (i + 1)) == 0) {   // complete min level
        if (i == size) {
          // go to bottom max level
          int bits = 31 - Integer.numberOfLeadingZeros(i);
          return (1 << bits) - 2;
        }
        i = (i + 1) << 1;         // start next min level
        if (i >= size) {
          return size - 1;
        }
      } else {
        i++;
        if (i > size) {
          // go to bottom max level
          int bits = 31 - Integer.numberOfLeadingZeros(i);
          return (1 << bits) - 2;
        }
      }
    } else {                      // we are at max level
      i--;
      // decreasing index resulted complete min level
      if ((i & (i + 1)) == 0) {
        i >>>= 1;
      }
      if (i < 1) {
        return -1;
      }
    }
    return i - 1;
  }