class TimeRange implements Comparable<TimeRange> {

  @SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity warning
  public List<TimeRange> getRemains(List<TimeRange> timeRangesPrev) {
    List<TimeRange> remains = new ArrayList<>();

    for (TimeRange prev : timeRangesPrev) {
      // +2 is to keep consistent with the definition of `intersects` of two closed intervals
      if (prev.min >= max + 2) {
        // break early since timeRangesPrev is sorted
        break;
      }

      if (intersects(prev)) {
        if (prev.contains(this)) {
          // e.g., this=[3,5], prev=[1,10]
          // e.g., this=[3,5], prev=[3,5] Note that in this case, prev contains this and vice versa.
          return remains;
        } else if (this.contains(prev)) {
          if (prev.min > this.min && prev.max == this.max) {
            // e.g., this=[1,6], prev=[3,6]
            this.setMax(prev.min);
            this.setRightClose(false);
            remains.add(this);
            // return the final result because timeRangesPrev is sorted
            return remains;
          } else if (prev.min == this.min) {
            // Note prev.max < this.max e.g., this=[1,10], prev=[1,4]
            min = prev.max;
            leftClose = false;
          } else {
            // e.g., prev=[3,6], this=[1,10]
            TimeRange r = new TimeRange(this.min, prev.min);
            r.setLeftClose(this.leftClose);
            r.setRightClose(false);
            remains.add(r);
            min = prev.max;
            leftClose = false;
          }
        } else {
          // intersect without one containing the other
          if (prev.min < this.min) {
            // e.g., this=[3,10], prev=[1,6]
            min = prev.max;
            leftClose = false;
          } else {
            // e.g., this=[1,8], prev=[5,12]
            this.setMax(prev.min);
            this.setRightClose(false);
            remains.add(this);
            // return the final result because timeRangesPrev is sorted
            return remains;
          }
        }
      }
    }

    remains.add(this);
    return remains;
  }

  public  TimeRange(long min, long max);

}