content: package pers.neige.neigeitems.utils.pagination;
  
  import lombok.NonNull;
  import pers.neige.neigeitems.utils.pagination.impl.ImmutableListPager;
  import pers.neige.neigeitems.utils.pagination.impl.MutableListPager;
  import pers.neige.neigeitems.utils.pagination.impl.MutableNavMapPager;
  import pers.neige.neigeitems.utils.pagination.impl.MutableNavSetPager;
  
  import java.util.*;
  
  /**
   * 分页工具, 非并发安全(曾尝试进行并发安全处理, 但失败了)
   */
  public abstract class Pager<T> {
      /**
       * 页面信息
       */
      protected final @NonNull PagerInfo pagerInfo;
  
      protected Pager(int pageSize) {
          this.pagerInfo = new PagerInfo(Math.max(1, pageSize));
      }
  
      /**
       * 根据一个不可变 List 创建分页工具.<br>
       * 元素顺序为迭代器遍历顺序.<br>
       * 如果 clone 项为 true, 此后对该 List 的任何修改将无法反应到已创建的分页工具中.<br>
       * 如果 clone 项为 false, 此后对该 List 的任何修改将导致不可预知的错误.<br>
       * pageSize 小于等于 0 时将自动变为 1.
       *
       * @param handle   待分页 List
       * @param pageSize 页大小
       * @param clone    是否对传入的 List 进行复制
       * @return 分页工具
       */
      public static <T> @NonNull Pager<T> fromImmutableList(@NonNull List<T> handle, int pageSize, boolean clone) {
          return new ImmutableListPager<>(clone ? Collections.unmodifiableList(new ArrayList<>(handle)) : handle, pageSize);
      }
  
      /**
       * 根据一个不可变数组创建分页工具.<br>
       * 元素顺序为数组顺序.<br>
       * 此后对该数组的任何修改将无法反应到已创建的分页工具中.<br>
       * pageSize 小于等于 0 时将自动变为 1.
       *
       * @param handle   待分页数组
       * @param pageSize 页大小
       * @return 分页工具
       */
      public static <T> @NonNull Pager<T> fromImmutableArray(T @NonNull [] handle, int pageSize) {
          return fromImmutableList(Arrays.asList(handle), pageSize, true);
      }
  
      /**
       * 根据一个不可变 Set 创建分页工具.<br>
       * 元素顺序为迭代器遍历顺序.<br>
       * 此后对该 Set 的任何修改将无法反应到已创建的分页工具中.<br>
       * pageSize 小于等于 0 时将自动变为 1.
       *
       * @param handle   待分页 Set
       * @param pageSize 页大小
       * @return 分页工具
       */
      public static <T> @NonNull Pager<T> fromImmutableSet(@NonNull Set<T> handle, int pageSize) {
          return fromImmutableList(Collections.unmodifiableList(new ArrayList<>(handle)), pageSize, false);
      }
  
      /**
       * 根据一个不可变 Map 创建分页工具.<br>
       * 元素顺序为迭代器遍历顺序.<br>
       * 此后对该 Map 的任何修改将无法反应到已创建的分页工具中.<br>
       * pageSize 小于等于 0 时将自动变为 1.
       *
       * @param handle   待分页 Map
       * @param pageSize 页大小
       * @return 分页工具
       */
      public static <K, V> @NonNull Pager<Map.Entry<K, V>> fromImmutableMap(@NonNull Map<K, V> handle, int pageSize) {
          return fromImmutableList(Collections.unmodifiableList(new ArrayList<>(handle.entrySet())), pageSize, false);
      }
  
      /**
       * 根据一个可变 List 创建分页工具.<br>
       * 元素顺序为迭代器遍历顺序.<br>
       * 此后对该 List 的任何修改将即时反应于已创建的分页工具中.<br>
       * pageSize 小于等于 0 时将自动变为 1.
       *
       * @param handle   待分页 List
       * @param pageSize 页大小
       * @return 分页工具
       */
      public static <T> @NonNull Pager<T> fromMutableList(@NonNull List<T> handle, int pageSize) {
          return new MutableListPager<>(handle, pageSize);
      }
  
      /**
       * 根据一个可变 NavigableSet 创建分页工具.<br>
       * 元素顺序为迭代器遍历顺序.<br>
       * 此后对该 NavigableSet 的任何修改将即时反应于已创建的分页工具中.<br>
       * pageSize 小于等于 0 时将自动变为 1.
       *
       * @param handle   待分页 Set
       * @param pageSize 页大小
       * @return 分页工具
       */
      public static <T> @NonNull Pager<T> fromMutableNavSet(@NonNull NavigableSet<T> handle, int pageSize) {
          return new MutableNavSetPager<>(handle, pageSize);
      }
  
      /**
       * 根据一个可变 NavigableMap 创建分页工具.<br>
       * 元素顺序为迭代器遍历顺序.<br>
       * 此后对该 NavigableMap 的任何修改将即时反应于已创建的分页工具中.<br>
       * pageSize 小于等于 0 时将自动变为 1.
       *
       * @param handle   待分页 Map
       * @param pageSize 页大小
       * @return 分页工具
       */
      public static <K, V> @NonNull Pager<Map.Entry<K, V>> fromMutableNavMap(@NonNull NavigableMap<K, V> handle, int pageSize) {
          return new MutableNavMapPager<>(handle, pageSize);
      }
  
      /**
       * 获取分页大小
       *
       * @return 分页大小
       */
      public int getPageSize() {
          return this.pagerInfo.getPageSize();
      }
  
      /**
       * 跳转到第一页（如果存在）
       *
       * @return 是否存在任意元素
       */
      public boolean firstPage() {
          return goToPage(1);
      }
  
      /**
       * 跳转到最后一页（如果存在）
       *
       * @return 是否存在任意元素
       */
      public boolean lastPage() {
          return goToPage(getTotalPages());
      }
  
      /**
       * 跳转到下一页（如果存在）
       *
       * @return 是否存在下一页
       */
      public abstract boolean nextPage();
  
      /**
       * 跳转到上一页（如果存在）
       *
       * @return 是否存在上一页
       */
      public abstract boolean prevPage();
  
      /**
       * 跳转到指定页
       *
       * @param page 目标页码（从1开始）
       * @return 页码是否有效
       */
      public abstract boolean goToPage(int page);
  
      /**
       * 获取当前页码（从1开始）
       */
      public abstract int getCurrentPage();
  
      /**
       * 获取当前页的元素列表
       */
      public abstract @NonNull List<T> getCurrentPageElements();
  
      /**
       * 检查是否存在下一页
       */
      public abstract boolean hasNextPage();
  
      /**
       * 检查是否存在上一页
       */
      public abstract boolean hasPrevPage();
  
      /**
       * 获取总页数
       */
      public int getTotalPages() {
          return this.pagerInfo.getTotalPages(getTotalElements());
      }
  
      /**
       * 获取总元素数
       */
      public abstract int getTotalElements();
  }
  