private function getBestMediaTypeFormatterMatch(
        string $type,
        array $formatters,
        array $mediaTypeHeaders,
        string $ioType
    ): ?MediaTypeFormatterMatch {
        // Rank the media type headers if they are rankable
        if (count($mediaTypeHeaders) > 0 && $mediaTypeHeaders[0] instanceof IHeaderValueWithQualityScore) {
            $mediaTypeHeaders = $this->rankAcceptMediaTypeHeaders($mediaTypeHeaders);
        }

        foreach ($mediaTypeHeaders as $mediaTypeHeader) {
            [$mediaType, $mediaSubType] = explode('/', $mediaTypeHeader->getMediaType());

            foreach ($formatters as $formatter) {
                foreach ($formatter->getSupportedMediaTypes() as $supportedMediaType) {
                    if ($ioType === self::FORMATTER_TYPE_INPUT && !$formatter->canReadType($type)) {
                        continue;
                    }

                    if ($ioType === self::FORMATTER_TYPE_OUTPUT && !$formatter->canWriteType($type)) {
                        continue;
                    }

                    [$supportedType, $supportedSubType] = explode('/', $supportedMediaType);

                    // Checks if the type is a wildcard or a match and the sub-type is a wildcard or a match
                    if (
                        $mediaType === '*' ||
                        ($mediaSubType === '*' && $mediaType === $supportedType) ||
                        ($mediaType === $supportedType && $mediaSubType === $supportedSubType)
                    ) {
                        return new MediaTypeFormatterMatch($formatter, $supportedMediaType, $mediaTypeHeader);
                    }
                }
            }
        }

        return null;
    }