// ignore_for_file: unnecessary_getters_setters

import 'dart:math' as math;

class IntRect {
  static final IntRect empty = IntRect();

  int _left = 0;
  int _top = 0;
  int _right = 0;
  int _bottom = 0;

  IntRect();

  factory IntRect.fill(
    int left,
    int top,
    int width,
    int height,
  ) {
    final rect = IntRect()
      .._left = left
      .._top = top
      .._right = left + width
      .._bottom = top + height;
    return rect;
  }

  int get left => _left;
  set left(int value) => _left = value;

  int get right => _right;
  set right(int value) => _right = value;

  int get top => _top;
  set top(int value) => _top = value;

  int get bottom => _bottom;
  set bottom(int value) => _bottom = value;

  int get x => _left;

  int get y => _top;

  int get width => _right - _left;
  int get height => _bottom - _top;

  bool get isEmpty {
    return _left == 0 && _top == 0 && _right == 0 && _bottom == 0;
  }

  bool isValid() {
    return _left >= 0 && _top >= 0 && _right > _left && _bottom > _top;
  }

  void reset() {
    _left = 0;
    _top = 0;
    _right = 0;
    _bottom = 0;
  }

  void union(IntRect deltaRect) {
    _left = math.min(_left, deltaRect._left);
    _right = math.max(_right, deltaRect._right);

    _top = math.min(_top, deltaRect._top);
    _bottom = math.max(_bottom, deltaRect._bottom);
  }

  void addOffset(int x, int y) {
    _left += x;
    _right += x;
    _top += y;
    _bottom += y;
  }

  bool intersectsWith(IntRect rect) {
    return _left < _right &&
        _top < _bottom &&
        rect._left < rect._right &&
        rect._top < rect._bottom &&
        _right > rect._left &&
        _left < rect._right &&
        _bottom > rect._top &&
        _top < rect._bottom;
  }

  void intersect(IntRect rect) {
    if (!intersectsWith(rect)) {
      reset();
      return;
    }

    _left = math.max(_left, rect._left);
    _top = math.max(_top, rect._top);
    _right = math.min(_right, rect._right);
    _bottom = math.min(_bottom, rect._bottom);
  }

  @override
  bool operator ==(Object other) {
    return other is IntRect &&
        _left == other._left &&
        _top == other._top &&
        _right == other._right &&
        _bottom == other._bottom;
  }

  @override
  int get hashCode {
    int hashCode = _left;
    hashCode = (hashCode * 397) ^ _top;
    hashCode = (hashCode * 397) ^ _right;
    hashCode = (hashCode * 397) ^ _bottom;
    return hashCode;
  }

  @override
  String toString() => '$x,$y,$width,$height';
}
