public static function getRangeInfo(string $isbn) : ?RangeInfo
    {
        $length = strlen($isbn);
        $isbnPrefix = ($length === 10) ? '978' : substr($isbn, 0, 3);
        $isbnDigits = ($length === 10) ? $isbn : substr($isbn, 3);

        foreach (self::getRanges() as $rangeData) {
            list ($eanPrefix, $groupIdentifier, $groupName, $ranges) = $rangeData;

            if ($isbnPrefix !== $eanPrefix) {
                continue;
            }

            $groupLength = strlen($groupIdentifier);
            $isbnGroup = substr($isbnDigits, 0, $groupLength);

            if ($isbnGroup !== $groupIdentifier) {
                continue;
            }

            $rangeInfo = new RangeInfo;
            $rangeInfo->groupIdentifier = ($length === 10 ? $groupIdentifier : $eanPrefix . '-' . $groupIdentifier);
            $rangeInfo->groupName = $groupName;

            foreach ($ranges as $range) {
                list ($rangeLength, $rangeStart, $rangeEnd) = $range;
                $rangeValue = substr($isbnDigits, $groupLength, $rangeLength);
                $lastDigits = substr($isbnDigits, $groupLength + $rangeLength, -1);
                $checkDigit = substr($isbnDigits, -1);

                if (strcmp($rangeValue, $rangeStart) >= 0 && strcmp($rangeValue, $rangeEnd) <= 0) {
                    if ($length === 13) {
                        $rangeInfo->parts = [$isbnPrefix, $isbnGroup, $rangeValue, $lastDigits, $checkDigit];
                    } else {
                        $rangeInfo->parts = [$isbnGroup, $rangeValue, $lastDigits, $checkDigit];
                    }

                    break;
                }
            }

            return $rangeInfo;
        }

        return null;
    }