class_name IntRange extends RefCounted

static var Zero = IntRange.new(0, 0)

var minmax: PackedInt32Array

var min: int:
    get: return minmax[0]

var max: int:
    get:
        if inclusive: return minmax[1] + 1
        else: return minmax[1]

var inclusive: bool

func _init(start: int, end: int, inclusive: bool = false) -> void:
    minmax = PackedInt32Array([start, end])
    self.inclusive = inclusive

func _to_string() -> String:
    var ch = "]" if inclusive else ")"
    return "IntRange [%s, %s%s" % [min, max, ch]

func length() -> int:
    return absi(max - min)

func is_zero() -> bool:
    return min == 0 and max == 0

func is_empty() -> bool:
    return length() == 0

func iter(step: int = 1) -> RangeIterator:
    return RangeIterator.new(self, min, step)

func clamp(value: int) -> int:
    return clampi(value, minmax[0], minmax[1])

func wrap(value: int) -> int:
    return wrapi(value, minmax[0], minmax[1])

func contains(value: int) -> bool:
    return value >= min and value < max

func is_superset_of(range: IntRange) -> bool:
    return contains(range.min) and contains(range.max)

func is_subset_of(range: IntRange) -> bool:
    return range.is_superset_of(self)

func overlaps(range: IntRange) -> bool:
    return contains(range.min) or range.contains(min) or contains(range.max) or range.contains(max)

func difference(other: IntRange) -> Set:
    if is_subset_of(other):
        return Set.empty()
    elif not overlaps(other):
        return Set.from_iter(iter())

    return Set.from_iter(iter()).difference(Set.from_iter(other.iter()))

func union(other: IntRange) -> Set:
    return Set.from_iter(iter()).union(Set.from_iter(other.iter()))

func intersect(other: IntRange) -> Set:
    return Set.from_iter(iter()).intersect(Set.from_iter(other.iter()))
