<?PHP
/**
 * This script contains tests for the time name splitter.
 *
 * @author Joshua Ramon Enslin <joshua@museum-digital.de>
 */
declare(strict_types = 1);

use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Small;
use PHPUnit\Framework\Attributes\DataProvider;

/**
 * This script contains tests for the time name splitter.
 */
#[small]
#[CoversClass(\NodaTimeSplitter::class)]
final class NodaTimeSplitterTest extends TestCase {
    /**
     * Data provider for German time names.
     *
     * @return array<string, array{0: string, 1: NodaSplitTime, 2: string}>
     */
    public static function splittableGermanTimeNamesProvider():array {

        return [
            "1920er Jahre" => [
                "1920er Jahre",
                new NodaSplitTime('1920', '1929',
                    start_date: '1920-01-01',
                    end_date: '1929-12-31'),
                "1920-1929",
            ],
            "20er" => [
                "20er",
                new NodaSplitTime('1920', '1929',
                    start_date: '1920-01-01',
                    end_date: '1929-12-31'),
                "1920-1929",
            ],
            "2. Januar 2020" => [
                "2. Januar 2020",
                new NodaSplitTime('2020', '2020',
                    counting_time_month: '01',
                    counting_time_day: '02',
                    start_date: '2020-01-02',
                    end_date: '2020-01-02'),
                "02.01.2020",
            ],
            "02.01.2020" => [
                "02.01.2020",
                new NodaSplitTime('2020', '2020',
                    counting_time_month: '01',
                    counting_time_day: '02',
                    start_date: '2020-01-02',
                    end_date: '2020-01-02'),
                "02.01.2020",
            ],
            "2.1.2020" => [
                "2.1.2020",
                new NodaSplitTime('2020', '2020',
                    counting_time_month: '01',
                    counting_time_day: '02',
                    start_date: '2020-01-02',
                    end_date: '2020-01-02'),
                "02.01.2020",
            ],
            "?.1.2020" => [
                "?.1.2020",
                new NodaSplitTime('2020', '2020',
                    counting_time_month: '01',
                    start_date: '2020-01-01',
                    end_date: '2020-01-31'),
                "Januar 2020",
            ],
            "? 2020" => [
                "? 2020",
                new NodaSplitTime('2020', '2020',
                    start_date: '2020-01-01',
                    end_date: '2020-12-31'),
                "2020",
            ],
            "?.?.2020" => [
                "?.?.2020",
                new NodaSplitTime('2020', '2020',
                    start_date: '2020-01-01',
                    end_date: '2020-12-31'),
                "2020",
            ],
            "?.10.2020" => [
                "?.10.2020",
                new NodaSplitTime('2020', '2020',
                    counting_time_month: '10',
                    start_date: '2020-10-01',
                    end_date: '2020-10-31'),
                "Oktober 2020",
            ],
            "20. Jh." => [
                "20. Jh.",
                new NodaSplitTime('1901', '2000',
                    start_date: '1901-01-01',
                    end_date: '2000-12-31'),
                "1901-2000",
            ],
            "20. Jhd." => [
                "20. Jhd.",
                new NodaSplitTime('1901', '2000',
                    start_date: '1901-01-01',
                    end_date: '2000-12-31'),
                "1901-2000",
            ],
            "20. Jhdt." => [
                "20. Jhdt.",
                new NodaSplitTime('1901', '2000',
                    start_date: '1901-01-01',
                    end_date: '2000-12-31'),
                "1901-2000",
            ],
            "20. Jahrhundert" => [
                "20. Jahrhundert",
                new NodaSplitTime('1901', '2000',
                    start_date: '1901-01-01',
                    end_date: '2000-12-31'),
                "1901-2000",
            ],
            "1945-48" => [
                "1945-48",
                new NodaSplitTime('1945', '1948',
                    start_date: '1945-01-01',
                    end_date: '1948-12-31'),
                "1945-1948",
            ],
            "1945 und 1946" => [
                "1945 und 1946",
                new NodaSplitTime('1945', '1946',
                    start_date: '1945-01-01',
                    end_date: '1946-12-31'),
                "1945-1946",
            ],
            "1945 oder 1946" => [
                "1945 oder 1946",
                new NodaSplitTime('1945', '1946',
                    start_date: '1945-01-01',
                    end_date: '1946-12-31'),
                "1945-1946",
            ],
            "1945 bis 2046" => [
                "1945 bis 2046",
                new NodaSplitTime('1945', '2046',
                    start_date: '1945-01-01',
                    end_date: '2046-12-31'),
                "1945-2046",
            ],
            "1945–2046" => [
                "1945 bis 2046",
                new NodaSplitTime('1945', '2046',
                    start_date: '1945-01-01',
                    end_date: '2046-12-31'),
                "1945-2046",
            ],
            "1930–2017" => [
                "1930–2017",
                new NodaSplitTime('1930', '2017',
                    start_date: '1930-01-01',
                    end_date: '2017-12-31'),
                "1930-2017",
            ],
            "18 v. Chr." => [
                "18 v. Chr.",
                new NodaSplitTime('-18', '-18',
                    counting_time_indicator: NodaCountingTimeIndicator::bce,
                    start_date: '-0018-01-01',
                    end_date: '-0018-12-31'),
                "18 v. Chr.",
            ],
            "843-1100" => [
                "843-1100",
                new NodaSplitTime('0843', '1100',
                    start_date: '0843-01-01',
                    end_date: '1100-12-31'),
                "843-1100",
            ],
            "2-7 n. Chr." => [
                "2-7 n. Chr.",
                new NodaSplitTime('0002', '0007',
                    start_date: '0002-01-01',
                    end_date: '0007-12-31'),
                "2-7 n. Chr.",
            ],
            "0-280 n. Chr." => [
                "0-280 n. Chr.",
                new NodaSplitTime('0000', '0280',
                    start_date: '0000-01-01',
                    end_date: '0280-12-31'),
                "0-280 n. Chr.",
            ],
            "280-10 v. Chr." => [
                "280-10 v. Chr.",
                new NodaSplitTime('-280', '-10',
                    counting_time_indicator: NodaCountingTimeIndicator::bce,
                    start_date: '-0280-01-01',
                    end_date: '-0010-12-31'),
                "280-10 v. Chr.",
            ],
            "28-1 v. Chr." => [
                "28-1 v. Chr.",
                new NodaSplitTime('-28', '-1',
                    counting_time_indicator: NodaCountingTimeIndicator::bce,
                    start_date: '-0028-01-01',
                    end_date: '-0001-12-31'),
                "28-1 v. Chr.",
            ],
        ];

    }

    /**
     * Data provider for English time names.
     *
     * @return array<string, array{0: string, 1: NodaSplitTime, 2: string}>
     */
    public static function splittableEnglishTimeNamesProvider():array {

        return [
            "1925 BCE" => [
                "1925 BCE",
                new NodaSplitTime('-1925', '-1925',
                    counting_time_indicator: NodaCountingTimeIndicator::bce,
                    start_date: '-1925-01-01',
                    end_date: '-1925-12-31'),
                "1925 v. Chr.",
            ],
            "1925 CE" => [
                "1925",
                new NodaSplitTime('1925', '1925'),
                "1925",
            ],
        ];

    }

    /**
     * Data provider for Hungarian time names.
     *
     * @return array<string, array{0: string, 1: NodaSplitTime, 2: string}>
     */
    public static function splittableHungarianTimeNamesProvider():array {

        return [
            '1920-es evek: 1920s' => [
                "1920-es évek",
                new NodaSplitTime('1920', '1929',
                    start_date: '1920-01-01',
                    end_date: '1929-12-31'),
                "1920-1929",
            ],
            '1920 es evekig: Until the 1920s' => [
                "1920 es évekig",
                new NodaSplitTime('?', '1929',
                    before_after_indicator: NodaTimeBeforeAfterIndicator::until,
                    end_date: '1929-12-31'),
                "Bis 1929",
            ],
            '1920-es evekig: Until the 1920s' => [
                "1920-es évekig",
                new NodaSplitTime('?', '1929',
                    before_after_indicator: NodaTimeBeforeAfterIndicator::until,
                    end_date: '1929-12-31'),
                "Bis 1929",
            ],
            'year + month' => [
                "2020. Januar",
                new NodaSplitTime('2020', '2020',
                    counting_time_month: '01',
                    start_date: '2020-01-01',
                    end_date: '2020-01-31'),
                "Januar 2020",
            ],
            'Kr. e. (BC) + year + month' => [
                "Kr. e. 2020. Januar",
                new NodaSplitTime('-2020', '-2020',
                    counting_time_month: '01',
                    counting_time_indicator: NodaCountingTimeIndicator::bce,
                    start_date: '-2020-01-31',
                    end_date: '-2020-01-01'),
                "Januar 2020 v. Chr.",
            ],
            '[0-9]{2}. sz' => [
                "20. sz",
                new NodaSplitTime('1901', '2000',
                    start_date: '1901-01-01',
                    end_date: '2000-12-31'),
                "1901-2000",
            ],
            '[0-9]{2}. század' => [
                "20. század",
                new NodaSplitTime('1901', '2000',
                    start_date: '1901-01-01',
                    end_date: '2000-12-31'),
                "1901-2000",
            ],
            '[0-9]{2}.század' => [
                "20.század",
                new NodaSplitTime('1901', '2000',
                    start_date: '1901-01-01',
                    end_date: '2000-12-31'),
                "1901-2000",
            ],
            'Kr. e. (BC) + század' => [
                "Kr. e. 20. század",
                new NodaSplitTime('-2000', '-1901',
                    counting_time_indicator: NodaCountingTimeIndicator::bce,
                    start_date: '-2000-12-31',
                    end_date: '-1901-01-01'),
                "2000-1901 v. Chr.",
            ],
            'Kr. e. (BC) + 20-19' => [
                "Kr. e. 20.-19. század",
                new NodaSplitTime('-2000', '-1801',
                    counting_time_indicator: NodaCountingTimeIndicator::bce,
                    start_date: '-1801-12-31',
                    end_date: '-2000-01-01'),
                "2000-1801 v. Chr.",
            ],
            'Kr. e. (BC) + 20-19 + ig (until)' => [
                "Kr. e. 20.-19. század-ig",
                new NodaSplitTime('?', '-1801',
                    counting_time_indicator: NodaCountingTimeIndicator::bce,
                    before_after_indicator: NodaTimeBeforeAfterIndicator::until,
                    start_date: '-9999-12-31',
                    end_date: '-2000-01-01'),
                "Bis 1801 v. Chr.",
            ],
            'year + suffix: -ig (until)' => [
                '1900ig',
                new NodaSplitTime('?', '1900',
                    before_after_indicator: NodaTimeBeforeAfterIndicator::until,
                    start_date: '-9999-12-31',
                    end_date: '1900-12-31'),
                "Bis 1900",
            ],
            'year + suffix: ig (until)' => [
                '1900ig',
                new NodaSplitTime('?', '1900',
                    before_after_indicator: NodaTimeBeforeAfterIndicator::until,
                    start_date: '-9999-12-31',
                    end_date: '1900-12-31'),
                "Bis 1900",
            ],
            'year előtt (before)' => [
                '2020. előtt',
                new NodaSplitTime('?', '2019',
                    before_after_indicator: NodaTimeBeforeAfterIndicator::before,
                    start_date: '-9999-12-31',
                    end_date: '2020-01-01'),
                'Vor 2020',
            ],
            'year, month + előtt (before)' => [
                '2020. december előtt',
                new NodaSplitTime('?', '2020',
                    counting_time_month: '12',
                    before_after_indicator: NodaTimeBeforeAfterIndicator::before,
                    start_date: '-9999-12-31',
                    end_date: '2020-12-01'),
                'Vor Dezember 2020',
            ],
        ];

    }

    /**
     * Data provider for Ukrainian time names.
     *
     * @return array<string, array{0: string, 1: NodaSplitTime}>
     */
    public static function splittableUkrainianTimeNamesProvider():array {

        return [
            'Year + p' => [
                '2020 p',
                new NodaSplitTime('2020', '2020',
                    start_date: '2020-01-01',
                    end_date: '2020-12-31'),
            ],
        ];

    }

    /**
     * Data provider for time names that the time splitter should not
     * be able to split.
     *
     * @return array<string, array{0: string, 1: array{start_name: string, end_name: string, start_year: string, end_year: string, start_date: string, end_date: string, counting_time_year: string, counting_time_month: string, counting_time_day: string, counting_time_bcce: string}}>
     */
    public static function timeNamesToSplitFromTillProvider():array {

        $output = [];

        foreach ([
            "2004.01.-2004.02." => [
                'start_name' => "Januar 2004",
                'end_name' => "Februar 2004",
                "start_year" => '2004',
                "end_year" => '2004',
                'start_date' => '2004-01-01',
                'end_date' => '2004-02-31',
                "counting_time_year" => "2004",
                "counting_time_month" => "02",
                "counting_time_day" => "01",
                "counting_time_bcce" => "+",
            ],
            "2004.01.-02." => [
                'start_name' => "Januar 2004",
                'end_name' => "Februar 2004",
                "start_year" => '2004',
                "end_year" => '2004',
                'start_date' => '2004-01-01',
                'end_date' => '2004-02-31',
                "counting_time_year" => "2004",
                "counting_time_month" => "02",
                "counting_time_day" => "01",
                "counting_time_bcce" => "+",
            ],
            "2003.04-05." => [
                'start_name' => "April 2003",
                'end_name' => "Mai 2003",
                "start_year" => '2003',
                "end_year" => '2003',
                'start_date' => '2003-04-01',
                'end_date' => '2003-05-31',
                "counting_time_year" => "2003",
                "counting_time_month" => "05",
                "counting_time_day" => "01",
                "counting_time_bcce" => "+",
            ],
            "1981. július-augusztus" => [
                'start_name' => "Juli 1981",
                'end_name' => "August 1981",
                "start_year" => '1981',
                "end_year" => '1981',
                'start_date' => '1981-07-01',
                'end_date' => '1981-08-31',
                "counting_time_year" => "1981",
                "counting_time_month" => "08",
                "counting_time_day" => "01",
                "counting_time_bcce" => "+",
            ],
            "2019.03.14.,04.15." => [
                'start_name' => "14.03.2019",
                'end_name' => "15.04.2019",
                "start_year" => '2019',
                "end_year" => '2019',
                'start_date' => '2019-03-14',
                'end_date' => '2019-04-15',
                "counting_time_year" => "2019",
                "counting_time_month" => "03",
                "counting_time_day" => "30",
                "counting_time_bcce" => "+",
            ],
            "14.-15.03.2019" => [
                'start_name' => "14.03.2019",
                'end_name' => "15.03.2019",
                "start_year" => '2019',
                "end_year" => '2019',
                'start_date' => '2019-03-14',
                'end_date' => '2019-03-15',
                "counting_time_year" => "2019",
                "counting_time_month" => "03",
                "counting_time_day" => "15",
                "counting_time_bcce" => "+",
            ],
            "3.-7.9.1819" => [
                'start_name' => "03.09.1819",
                'end_name' => "07.09.1819",
                "start_year" => '1819',
                "end_year" => '1819',
                'start_date' => '1819-09-03',
                'end_date' => '1819-09-07',
                "counting_time_year" => "1819",
                "counting_time_month" => "09",
                "counting_time_day" => "05",
                "counting_time_bcce" => "+",
            ],
            "3.-15.9.1819" => [
                'start_name' => "03.09.1819",
                'end_name' => "15.09.1819",
                "start_year" => '1819',
                "end_year" => '1819',
                'start_date' => '1819-09-03',
                'end_date' => '1819-09-15',
                "counting_time_year" => "1819",
                "counting_time_month" => "09",
                "counting_time_day" => "09",
                "counting_time_bcce" => "+",
            ],
            "14.-15.9.1819" => [
                'start_name' => "14.09.1819",
                'end_name' => "15.09.1819",
                "start_year" => '1819',
                "end_year" => '1819',
                'start_date' => '1819-09-14',
                'end_date' => '1819-09-15',
                "counting_time_year" => "1819",
                "counting_time_month" => "09",
                "counting_time_day" => "15",
                "counting_time_bcce" => "+",
            ],
            "14.-15.11.1819" => [
                'start_name' => "14.11.1819",
                'end_name' => "15.11.1819",
                "start_year" => '1819',
                "end_year" => '1819',
                'start_date' => '1819-11-14',
                'end_date' => '1819-11-15',
                "counting_time_year" => "1819",
                "counting_time_month" => "11",
                "counting_time_day" => "15",
                "counting_time_bcce" => "+",
            ],
            "2019.03.14-15" => [
                'start_name' => "14.03.2019",
                'end_name' => "15.03.2019",
                "start_year" => '2019',
                "end_year" => '2019',
                'start_date' => '2019-03-14',
                'end_date' => '2019-03-15',
                "counting_time_year" => "2019",
                "counting_time_month" => "03",
                "counting_time_day" => "15",
                "counting_time_bcce" => "+",
            ],
            "17-19.század" => [
                'start_name' => "1601",
                'end_name' => "1900",
                "start_year" => '1601',
                "end_year" => '1900',
                'start_date' => '1601-01-01',
                'end_date' => '1900-12-31',
                "counting_time_year" => "1751",
                "counting_time_month" => "01",
                "counting_time_day" => "01",
                "counting_time_bcce" => "+",
            ],
            "1950-60-as évek" => [
                'start_name' => "1950",
                'end_name' => "1969",
                "start_year" => '1950',
                "end_year" => '1969',
                'start_date' => '1950-01-01',
                'end_date' => '1969-12-31',
                "counting_time_year" => "1960",
                "counting_time_month" => "01",
                "counting_time_day" => "01",
                "counting_time_bcce" => "+",
            ],
            "1. Halbjahr 1950" => [
                'start_name' => "Januar 1950",
                'end_name' => "Juni 1950",
                "start_year" => '1950',
                "end_year" => '1950',
                'start_date' => '1950-01-01',
                'end_date' => '1950-06-31',
                "counting_time_year" => "1950",
                "counting_time_month" => "04",
                "counting_time_day" => "02",
                "counting_time_bcce" => "+",
            ],
        ] as $in => $out) {
            $output[$in] = [$in, $out];
        }

        return $output;

    }

    /**
     * Data provider for time names that the time splitter should not
     * be able to split.
     *
     * @return array<array{0: string}>
     */
    public static function nonSplittableNamesProvider():array {

        $output = [
            'empty string' => [''],
        ];

        foreach ([
            "30.02.2024",
            "31.11.2024",
            "31.4.2024",
            "1.2.2020-2.2.2020",
            "2020 Januar 2-2020 Februar 2",
            "2020 Januar-2020 Februar",
            "Januar-Februar",
            "13.13.2022",
            "2022-13-13",
            "40.10.2022",
            "2022-10-40",
            "6;November 1978",
            "65497028c51eb",
            "6552cf08b0196 test tag",
            "1978. július7",
            "1978. július 7 elött",
            "Anfang September 1903",
            "0-25 n. Chr.", // Should not be splittable because 25 CE is too close to 0. 0 might actually be correct, not an artefact.
        ] as $entry) {
            $output[$entry] = [$entry];
        }

        return $output;

    }

    /**
     * Test to check whether the HTML page is correctly generated.
     *
     * @author Joshua Ramon Enslin <joshua@museum-digital.de>
     * @group  ValidOutput
     * @small
     *
     * @return void
     */
    public function testSplitSimpleDatesGermanOld():void {

        $output = NodaTimeSplitter::attempt_splitting("02.1.25 v. Chr");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "-25",
            1 => "-25",
            2 => "01",
            3 => "02",
            4 => "-",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "02.01.25 v. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 25);

        $output = NodaTimeSplitter::attempt_splitting("2.01.25 v. Chr");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "-25",
            1 => "-25",
            2 => "01",
            3 => "02",
            4 => "-",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "02.01.25 v. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 25);

        $output = NodaTimeSplitter::attempt_splitting("02.01.25 v. Chr");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "-25",
            1 => "-25",
            2 => "01",
            3 => "02",
            4 => "-",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "02.01.25 v. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 25);

        $output = NodaTimeSplitter::attempt_splitting("2.1.25 v. Chr");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "-25",
            1 => "-25",
            2 => "01",
            3 => "02",
            4 => "-",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "02.01.25 v. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 25);

        $output = NodaTimeSplitter::attempt_splitting("02.01.2020");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "01",
            3 => "02",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "02.01.2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting(".2020");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("0-2020");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("2021-0");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2021",
            1 => "2021",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals("2021", $output->toTimeName());
        self::assertEquals(2021, NodaTimeSplitter::timePartsToCountingYear($output));

        $output = NodaTimeSplitter::attempt_splitting("1920-1929");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1920",
            1 => "1929",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "1920-1929");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1925);

        $output = NodaTimeSplitter::attempt_splitting("Vor Dezember 2020");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "?",
            1 => "2020",
            2 => "12",
            3 => "00",
            4 => "+",
            5 => "Vor",
        ]);
        self::assertEquals($output->toTimeName(), "Vor Dezember 2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("Vor 2020");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "?",
            1 => "2019",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "Vor",
        ]);
        self::assertEquals($output->toTimeName(), "Vor 2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("Nach Januar 2020");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "?",
            2 => "01",
            3 => "00",
            4 => "+",
            5 => "Nach",
        ]);
        self::assertEquals($output->toTimeName(), "Nach Januar 2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("Januar 2020");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "01",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "Januar 2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("Januar 1217");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1217",
            1 => "1217",
            2 => "01",
            3 => "00",
            4 => "+",
            5 => "",
        ]);

        self::assertEquals($output->toTimeName(), "Januar 1217");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1217);

        $output = NodaTimeSplitter::attempt_splitting("Januar 1520");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1520",
            1 => "1520",
            2 => "01",
            3 => "00",
            4 => "+",
            5 => "",
        ]);

        self::assertEquals($output->toTimeName(), "Januar 1520");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1520);

        $output = NodaTimeSplitter::attempt_splitting("Januar 1001");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1001",
            1 => "1001",
            2 => "01",
            3 => "00",
            4 => "+",
            5 => "",
        ]);

        self::assertEquals($output->toTimeName(), "Januar 1001");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1001);

        $output = NodaTimeSplitter::attempt_splitting("Januar 2780");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2780",
            1 => "2780",
            2 => "01",
            3 => "00",
            4 => "+",
            5 => "",
        ]);

        self::assertEquals($output->toTimeName(), "Januar 2780");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2780);

        $output = NodaTimeSplitter::attempt_splitting("Nach 60er Jahre");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1970",
            1 => "?",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "Nach",
        ]);
        self::assertEquals($output->toTimeName(), "Nach 1969");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1969);

        $output = NodaTimeSplitter::attempt_splitting("Nach 2020");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2021",
            1 => "?",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "Nach",
        ]);
        self::assertEquals($output->toTimeName(), "Nach 2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("Bis Januar 2020");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "?",
            1 => "2020",
            2 => "01",
            3 => "00",
            4 => "+",
            5 => "Bis",
        ]);
        self::assertEquals($output->toTimeName(), "Bis Januar 2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("Januar 2020");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "01",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "Januar 2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        // Intl' month: 2020-01
        $output = NodaTimeSplitter::attempt_splitting("2020-01");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "01",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "Januar 2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("Januar 2020 v. Chr.");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "-2020",
            1 => "-2020",
            2 => "01",
            3 => "00",
            4 => "-",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "Januar 2020 v. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        // 5-Digit timespans BCE
        $output = NodaTimeSplitter::attempt_splitting("40000-25000 vor Christus");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "-40000",
            1 => "-25000",
            2 => "00",
            3 => "00",
            4 => "-",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "40000-25000 v. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 32500);

        // 5-Digit timespans BCE
        $output = NodaTimeSplitter::attempt_splitting("40000-25000 v.C.");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "-40000",
            1 => "-25000",
            2 => "00",
            3 => "00",
            4 => "-",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "40000-25000 v. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 32500);

        $output = NodaTimeSplitter::attempt_splitting("20. Jahrhundert v. Chr.");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "-2000",
            1 => "-1901",
            2 => "00",
            3 => "00",
            4 => "-",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "2000-1901 v. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1950);

        $output = NodaTimeSplitter::attempt_splitting("20.-19. Jahrhundert v. Chr.");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "-2000",
            1 => "-1801",
            2 => "00",
            3 => "00",
            4 => "-",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "2000-1801 v. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1900);

        $output = NodaTimeSplitter::attempt_splitting("Bis 20.-19. Jahrhundert v. Chr.");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "?",
            1 => "-1801",
            2 => "00",
            3 => "00",
            4 => "-",
            5 => "Bis",
        ]);
        self::assertEquals($output->toTimeName(), "Bis 1801 v. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1801);

        $output = NodaTimeSplitter::attempt_splitting("15. 11. 1978");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1978",
            1 => "1978",
            2 => "11",
            3 => "15",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "15.11.1978");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1978);

        $output = NodaTimeSplitter::attempt_splitting("6 November 1978");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1978",
            1 => "1978",
            2 => "11",
            3 => "06",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "06.11.1978");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1978);

    }

    /**
     * Test that German dates are correctly parsed.
     *
     * @author Joshua Ramon Enslin <joshua@museum-digital.de>
     * @group  ValidOutput
     * @small
     *
     * @param string        $time_name     Input time name.
     * @param NodaSplitTime $expected      Expected output.
     * @param string        $expected_name Expected name.
     *
     * @return void
     */
    #[DataProvider('splittableGermanTimeNamesProvider')]
    public function testSplitSimpleDatesGerman(string $time_name, NodaSplitTime $expected, string $expected_name):void {

        $output = NodaTimeSplitter::attempt_splitting($time_name);
        self::assertEquals($expected, $output);
        self::assertEquals($expected_name, $output->toTimeName());

    }

    /**
     * Test that English dates are correctly parsed.
     *
     * @author Joshua Ramon Enslin <joshua@museum-digital.de>
     * @group  ValidOutput
     * @small
     *
     * @param string        $time_name     Input time name.
     * @param NodaSplitTime $expected      Expected output.
     * @param string        $expected_name Expected name.
     *
     * @return void
     */
    #[DataProvider('splittableEnglishTimeNamesProvider')]
    public function testSplitSimpleDatesEnglish(string $time_name, NodaSplitTime $expected, string $expected_name):void {

        $output = NodaTimeSplitter::attempt_splitting($time_name);
        self::assertEquals($expected, $output);
        self::assertEquals($expected_name, $output->toTimeName());

    }

    /**
     * Test that Hungarian dates are correctly parsed.
     *
     * @author Joshua Ramon Enslin <joshua@museum-digital.de>
     * @group  ValidOutput
     * @small
     *
     * @return void
     */
    public function testSplitSimpleDatesHungarian():void {

        $output = NodaTimeSplitter::attempt_splitting("Kr. e. 2. század");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "-200",
            1 => "-101",
            2 => "00",
            3 => "00",
            4 => "-",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "200-101 v. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 150);

        $output = NodaTimeSplitter::attempt_splitting("2020.01.02.");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "01",
            3 => "02",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "02.01.2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("2020. januar. 2.");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "01",
            3 => "02",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "02.01.2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("2020.01.2.");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "01",
            3 => "02",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "02.01.2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("2020.1.2.");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "01",
            3 => "02",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "02.01.2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("2020. Januar 2.");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "01",
            3 => "02",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "02.01.2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("2020-01-02");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "2020",
            1 => "2020",
            2 => "01",
            3 => "02",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "02.01.2020");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2020);

        $output = NodaTimeSplitter::attempt_splitting("1920-tól 1929-ig");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1920",
            1 => "1929",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "1920-1929");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1925);

        $output = NodaTimeSplitter::attempt_splitting("1920-1929 között");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1920",
            1 => "1929",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "1920-1929");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1925);

        $output = NodaTimeSplitter::attempt_splitting("1920-2929 között");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1920",
            1 => "2929",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "1920-2929");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 2425);

        $output = NodaTimeSplitter::attempt_splitting("1920-től 1929-ig");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1920",
            1 => "1929",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "1920-1929");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1925);

        // From 1920 onwards
        $output = NodaTimeSplitter::attempt_splitting("1920 utántól");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1920",
            1 => "?",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "Seit",
        ]);
        self::assertEquals($output->toTimeName(), "Seit 1920");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1920);

        $output = NodaTimeSplitter::attempt_splitting("III. század");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "201",
            1 => "300",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "201-300 n. Chr.");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 251);

        $output = NodaTimeSplitter::attempt_splitting("20th century");
        self::assertNotEmpty($output);
        self::assertEquals($output->toOldFormat(), [
            0 => "1901",
            1 => "2000",
            2 => "00",
            3 => "00",
            4 => "+",
            5 => "",
        ]);
        self::assertEquals($output->toTimeName(), "1901-2000");
        self::assertEquals(NodaTimeSplitter::timePartsToCountingYear($output), 1951);

    }

    /**
     * Test that Hungarian dates are correctly parsed.
     *
     * @author Joshua Ramon Enslin <joshua@museum-digital.de>
     * @group  ValidOutput
     * @small
     *
     * @param string        $time_name     Input time name.
     * @param NodaSplitTime $expected      Expected output.
     * @param string        $expected_name Expected name.
     *
     * @return void
     */
    #[DataProvider('splittableHungarianTimeNamesProvider')]
    public function testSplitSimpleDatesHungarianNew(string $time_name, NodaSplitTime $expected, string $expected_name):void {

        $output = NodaTimeSplitter::attempt_splitting($time_name);
        self::assertEquals($expected, $output);
        self::assertEquals($expected_name, $output->toTimeName());

    }

    /**
     * Test that Ukrainian dates are correctly parsed.
     *
     * @author Joshua Ramon Enslin <joshua@museum-digital.de>
     * @group  ValidOutput
     * @small
     *
     * @param string        $time_name Input time name.
     * @param NodaSplitTime $expected  Expected output.
     *
     * @return void
     */
    #[DataProvider('splittableUkrainianTimeNamesProvider')]
    public function testSplitSimpleDatesUkrainian(string $time_name, NodaSplitTime $expected):void {

        $output = NodaTimeSplitter::attempt_splitting($time_name);
        self::assertNotEmpty($output);
        self::assertEquals($expected, $output);

    }

    /**
     * Test to check that time spans can be parsed as expected.
     *
     * @author Joshua Ramon Enslin <joshua@museum-digital.de>
     * @group  ValidOutput
     * @small
     *
     * @param string                                                                                                                                                                                                                                  $time_name Input time name.
     * @param array{start_name: string, end_name: string, start_year: string, end_year: string, start_date: string, end_date: string, counting_time_year: string, counting_time_month: string, counting_time_day: string, counting_time_bcce: string} $expected  Expected values.
     *
     * @return void
     */
    #[DataProvider('timeNamesToSplitFromTillProvider')]
    public function testSplittingFromTill(string $time_name, array $expected):void {

        // Regular
        $output = NodaTimeSplitter::attempt_splitting_from_till($time_name);
        self::assertNotEmpty($output);
        self::assertEquals($expected, $output);

    }

    /**
     * Test to check special cases of timespans can be parsed.
     *
     * @return void
     */
    public function testSpecialCasesForTimespans():void {

        // Rewritten / 1950-60-as évek
        $output = NodaTimeSplitter::attempt_splitting("1400-1100 v. Chr.");
        self::assertNotEmpty($output);
        self::assertEquals('-1400', $output->start_year);
        self::assertEquals('-1400-01-01', $output->start_date);

        // Same start as end with day
        $output = NodaTimeSplitter::attempt_splitting("11.10.1991-11.10.1991");
        self::assertNotEmpty($output);
        self::assertEquals('1991', $output->start_year);
        self::assertEquals('1991-10-11', $output->start_date);
        self::assertEquals('1991', $output->end_year);
        self::assertEquals('1991-10-11', $output->end_date);

    }

    /**
     * Test to check whether the HTML page is correctly generated.
     *
     * @author Joshua Ramon Enslin <joshua@museum-digital.de>
     * @group  ValidOutput
     * @small
     *
     * @param string $unsplittable_name Name that the time splitter should not
     *                                  be able to split.
     *
     * @return void
     */
    #[DataProvider('nonSplittableNamesProvider')]
    public function testSplitDoesNotWorkWhenItShouldNot(string $unsplittable_name):void {

        $output = NodaTimeSplitter::attempt_splitting($unsplittable_name);
        self::assertEmpty($output, "Time name $unsplittable_name should not be split. It was split into:" . PHP_EOL . PHP_EOL . var_export($output, true));

    }
}