public static function typeComparator(): Closure
    {
        static $factsort = [];

        if (empty($factsort)) {
            $factsort = array_flip(self::FACT_ORDER);
        }

        return static function (Fact $a, Fact $b) use ($factsort): int {
            // Facts from same families stay grouped together
            // Keep MARR and DIV from the same families from mixing with events from other FAMs
            // Use the original order in which the facts were added
            if ($a->record instanceof Family && $b->record instanceof Family && $a->record !== $b->record) {
                return $a->sortOrder - $b->sortOrder;
            }

            $atag = $a->getTag();
            $btag = $b->getTag();

            // Events not in the above list get mapped onto one that is.
            if (!array_key_exists($atag, $factsort)) {
                if (preg_match('/^(_(BIRT|MARR|DEAT|BURI)_)/', $atag, $match)) {
                    $atag = $match[1];
                } else {
                    $atag = '_????_';
                }
            }

            if (!array_key_exists($btag, $factsort)) {
                if (preg_match('/^(_(BIRT|MARR|DEAT|BURI)_)/', $btag, $match)) {
                    $btag = $match[1];
                } else {
                    $btag = '_????_';
                }
            }

            // - Don't let dated after DEAT/BURI facts sort non-dated facts before DEAT/BURI
            // - Treat dated after BURI facts as BURI instead
            if ($a->attribute('DATE') !== '' && $factsort[$atag] > $factsort['BURI'] && $factsort[$atag] < $factsort['CHAN']) {
                $atag = 'BURI';
            }

            if ($b->attribute('DATE') !== '' && $factsort[$btag] > $factsort['BURI'] && $factsort[$btag] < $factsort['CHAN']) {
                $btag = 'BURI';
            }

            $ret = $factsort[$atag] - $factsort[$btag];

            // If facts are the same then put dated facts before non-dated facts
            if ($ret == 0) {
                if ($a->attribute('DATE') !== '' && $b->attribute('DATE') === '') {
                    return -1;
                }

                if ($b->attribute('DATE') !== '' && $a->attribute('DATE') === '') {
                    return 1;
                }

                // If no sorting preference, then keep original ordering
                $ret = $a->sortOrder - $b->sortOrder;
            }

            return $ret;
        };
    }