package org.xbib.files.ftp.test.parser;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.xbib.files.ftp.FTPFile;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.EnumSet;
import java.util.Locale;
import org.xbib.files.ftp.parser.ConfigurableFTPFileEntryParserImpl;
import org.xbib.files.ftp.parser.OS2FTPEntryParser;

public class OS2FTPEntryParserTest {

    private static final String[] badsamples = {
            "                 DIR   12-30-97   12:32  jbrekke",
            "     0    rsa    DIR   11-25-97   09:42  junk",
            "     0           dir   05-12-97   16:44  LANGUAGE",
            "     0           DIR   13-05-97   25:49  MPTN",
            "587823    RSA    DIR   Jan-08-97   13:58  OS2KRNL",
            // " 33280      A          1997-02-03  13:49  OS2LDR",
            "12-05-96  05:03PM       <DIR>          absoft2",
            "11-14-97  04:21PM                  953 AUDITOR3.INI"
    };

    private static final String[] goodsamples = {
            "     0           DIR   12-30-97   12:32  jbrekke",
            "     0           DIR   11-25-97   09:42  junk",
            "     0           DIR   05-12-97   16:44  LANGUAGE",
            "     0           DIR   05-19-97   12:56  local",
            "     0           DIR   05-12-97   16:52  Maintenance Desktop",
            "     0           DIR   05-13-97   10:49  MPTN",
            "587823    RSA    DIR   01-08-97   13:58  OS2KRNL",
            " 33280      A          02-09-97   13:49  OS2LDR",
            "     0           DIR   11-28-97   09:42  PC",
            "149473      A          11-17-98   16:07  POPUPLOG.OS2",
            "     0           DIR   05-12-97   16:44  PSFONTS",
            "     0           DIR   05-19-2000 12:56  local",
    };

    @Test
    public void testFirstGoodListing() {
        ConfigurableFTPFileEntryParserImpl parser = new OS2FTPEntryParser();
        parser.configure(null);
        for (String test : goodsamples) {
            FTPFile f = parser.parseFTPEntry(test);
            assertNotNull(f, "Failed to parse " + test);
        }
    }

    @Test
    public void testBadListing() {
        ConfigurableFTPFileEntryParserImpl parser = new OS2FTPEntryParser();
        parser.configure(null);
        for (String test : badsamples) {
            try {
                FTPFile f = parser.parseFTPEntry(test);
                assertNull(nullFileOrNullDate(f), "Should have Failed to parse <" + test + ">");
            } catch (DateTimeParseException e) {
                //
            }
        }
    }

    private FTPFile nullFileOrNullDate(FTPFile f) {
        if (f == null) {
            return null;
        }
        if (f.getTimestamp() == null) {
            return null;
        }
        return f;
    }
    @Test
    public void testParseFieldsOnDirectory() throws Exception {
        ConfigurableFTPFileEntryParserImpl parser = new OS2FTPEntryParser();
        parser.configure(null);
        FTPFile dir = parser.parseFTPEntry("     0           DIR   11-28-97   09:42  PC");
        assertNotNull(dir, "Could not parse entry.");
        assertTrue(dir.isDirectory(), "Should have been a directory.");
        assertEquals(0, dir.getSize());
        assertEquals("PC", dir.getName());
        assertNotNull(dir.getTimestamp(), "Could not parse time stamp.");
        assertEquals("Fri Nov 28 09:42:00 1997", dir.getTimestamp().format(df));
    }

    @Test
    public void testParseFieldsOnFile() throws Exception {
        ConfigurableFTPFileEntryParserImpl parser = new OS2FTPEntryParser();
        parser.configure(null);
        FTPFile file = parser.parseFTPEntry("5000000000      A          11-17-98   16:07  POPUPLOG.OS2");
        assertNotNull(file, "Could not parse entry.");
        assertTrue(file.isFile(), "Should have been a file.");
        assertEquals(5000000000L, file.getSize());
        assertEquals("POPUPLOG.OS2", file.getName());
        assertNotNull(file.getTimestamp(), "Could not parse time stamp.");
        assertEquals("Tue Nov 17 16:07:00 1998", file.getTimestamp().format(df));
    }

    static final DateTimeFormatter df = DateTimeFormatter
            .ofPattern("EEE MMM dd HH:mm:ss yyyy")
            .withZone(ZoneId.of("UTC"))
            .withLocale(Locale.US);


    @Test
    public void testDefaultPrecision() {
        testPrecision("     0           DIR   05-12-97   16:44  PSFONTS",
                EnumSet.of(ChronoUnit.MINUTES));
        testPrecision("     0           DIR   05-19-2000 12:56  local",
                EnumSet.of(ChronoUnit.MINUTES));
    }

    private void testPrecision(String listEntry, EnumSet<ChronoUnit> units) {
        ConfigurableFTPFileEntryParserImpl parser = new OS2FTPEntryParser();
        FTPFile file = parser.parseFTPEntry(listEntry);
        assertNotNull(file, "Could not parse " + listEntry);
        ZonedDateTime zonedDateTime = file.getTimestamp();
        assertNotNull(zonedDateTime, "Failed to parse time in " + listEntry);
        for (ChronoUnit unit : units) {
            assertTrue(zonedDateTime.isSupported(unit), "Expected set " + unit + " in " + listEntry);
        }
    }
}
