class PagingData {
  static const DEFAULT_LIMIT = 50;

  final int? minId;
  final int? maxId;
  final int? sinceId;
  final int? offset;
  final int limit;

  PagingData({
    this.minId,
    this.maxId,
    this.sinceId,
    this.offset,
    this.limit = DEFAULT_LIMIT,
  });

  factory PagingData.fromQueryParameters(Uri uri) {
    final minIdString = uri.queryParameters['min_id'];
    final maxIdString = uri.queryParameters['max_id'];
    final sinceIdString = uri.queryParameters['since_id'];
    final limitString =
        uri.queryParameters['limit'] ?? uri.queryParameters['count'];
    final offsetString = uri.queryParameters['offset'];
    return PagingData(
      minId: int.tryParse(minIdString ?? ''),
      maxId: int.tryParse(maxIdString ?? ''),
      sinceId: int.tryParse(sinceIdString ?? ''),
      offset: int.tryParse(offsetString ?? ''),
      limit: int.tryParse(limitString ?? '') ?? DEFAULT_LIMIT,
    );
  }

  String toQueryParameters({String limitKeyword = 'limit'}) {
    var pagingData = '$limitKeyword=$limit';
    if (minId != null) {
      pagingData = '$pagingData&min_id=$minId';
    }

    if (sinceId != null) {
      pagingData = '$pagingData&since_id=$sinceId';
    }

    if (maxId != null) {
      pagingData = '$pagingData&max_id=$maxId';
    }

    if (offset != null) {
      pagingData = '$pagingData&offset=$offset';
    }

    return pagingData;
  }

  bool get isLimitOnly =>
      minId == null && maxId == null && sinceId == null && offset == null;

  @override
  String toString() {
    return 'PagingData{maxId: $maxId, minId: $minId, sinceId: $sinceId, offset: $offset, limit: $limit}';
  }

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
          other is PagingData &&
              runtimeType == other.runtimeType &&
              minId == other.minId &&
              maxId == other.maxId &&
              sinceId == other.sinceId &&
              offset == other.offset &&
              limit == other.limit;

  @override
  int get hashCode =>
      minId.hashCode ^
      maxId.hashCode ^
      sinceId.hashCode ^
      offset.hashCode ^
      limit.hashCode;
}
