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 org.xbib.files.ftp.FTPFileEntryParser;

import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import org.xbib.files.ftp.parser.CompositeFileEntryParser;
import org.xbib.files.ftp.parser.OS400FTPEntryParser;
import org.xbib.files.ftp.parser.UnixFTPEntryParser;

public class OS400FTPEntryParserAdditionalTest {

    private static final String[][] badsamples = {
            {
        "QPGMR          135168 04/03/18 13:18:19 *FILE",
        "QPGMR          135168    03/24 13:18:19 *FILE",
        "QPGMR          135168 04/03/18 30:06:29 *FILE",
        "QPGMR                 04/03/18 13:18:19 *FILE      RPGUNITC1.FILE",
        "QPGMR          135168    03/24 13:18:19 *FILE      RPGUNITC1.FILE",
        "QPGMR          135168 04/03/18 30:06:29 *FILE      RPGUNITC1.FILE",
        "QPGMR                                   *MEM       ",
        "QPGMR          135168 04/03/18 13:18:19 *MEM       RPGUNITC1.FILE/RUCALLTST.MBR",
        "QPGMR          135168                   *MEM       RPGUNITC1.FILE/RUCALLTST.MBR",
        "QPGMR                 04/03/18 13:18:19 *MEM       RPGUNITC1.FILE/RUCALLTST.MBR",
        "QPGMR USR                               *MEM       RPGUNITC1.FILE/RUCALLTST.MBR"
            }
    };

    private static final String[][] goodsamples = {
            {
        "QPGMR                                   *MEM       RPGUNITC1.FILE/RUCALLTST.MBR",
        "QPGMR        16347136 29.06.13 15:45:09 *FILE      RPGUNIT.SAVF"
            }
    };

    @Test
    public void testConsistentListing() throws Exception {
        CompositeFileEntryParser parser = new CompositeFileEntryParser(new FTPFileEntryParser[] {
                new OS400FTPEntryParser(),
                new UnixFTPEntryParser()
        });
        for (String[] goodsample : goodsamples) {
            for (String test : goodsample) {
                FTPFile f = parser.parseFTPEntry(test);
                assertNotNull(f, "Failed to parse " + test);
                doAdditionalGoodTests(test, f);
            }
        }
    }

    @Test
    public void testBadListing() {
        CompositeFileEntryParser parser = new CompositeFileEntryParser(new FTPFileEntryParser[] {
                new OS400FTPEntryParser(),
                new UnixFTPEntryParser()
        });
        for (String[] badsample : badsamples) {
            for (String test : badsample) {
                try {
                    FTPFile f = parser.parseFTPEntry(test);
                    assertNull(nullFileOrNullDate(f), "Should have Failed to parse " + test);
                    //doAdditionalBadTests(test, f);
                } 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 {
        CompositeFileEntryParser parser = new CompositeFileEntryParser(new FTPFileEntryParser[] {
                new OS400FTPEntryParser(),
                new UnixFTPEntryParser()
        });
        FTPFile f = parser.parseFTPEntry("PEP             36864 04/03/24 14:06:34 *DIR       dir1/");
        assertNotNull(f, "Could not parse entry.");
        assertTrue(f.isDirectory(), "Should have been a directory.");
        assertEquals("PEP", f.getUser());
        assertEquals("dir1", f.getName());
        assertEquals(36864, f.getSize());
        ZonedDateTime zonedDateTime = ZonedDateTime.of(2004,
                Month.MARCH.getValue(), 24, 14, 6, 34, 0, ZoneId.of("UTC"));
        assertEquals(zonedDateTime, f.getTimestamp());

    }

    private void doAdditionalGoodTests(String test, FTPFile f) {
        if (test.startsWith("d")) {
            assertEquals( FTPFile.DIRECTORY_TYPE, f.getType(), "directory.type");
        }
    }

    @Test
    public void testParseFieldsOnFile() throws Exception {
        CompositeFileEntryParser parser = new CompositeFileEntryParser(new FTPFileEntryParser[] {
                new OS400FTPEntryParser(),
                new UnixFTPEntryParser()
        });
        FTPFile f = parser.parseFTPEntry("PEP              5000000000 04/03/24 14:06:29 *STMF      build.xml");
        assertNotNull(f, "Could not parse entry.");
        assertTrue(f.isFile(), "Should have been a file.");
        assertEquals("PEP", f.getUser());
        assertEquals("build.xml", f.getName());
        assertEquals(5000000000L, f.getSize());
        ZonedDateTime zonedDateTime = ZonedDateTime.of(2004,
                Month.MARCH.getValue(), 24, 14, 6, 29, 0, ZoneId.of("UTC"));
        assertEquals(zonedDateTime, f.getTimestamp());
    }
}
