package org.xbib.files.ftp.test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.xbib.files.ftp.FTPClient;
import org.xbib.files.ftp.FTPClientConfig;
import org.xbib.files.ftp.FTPFile;
import org.xbib.files.ftp.FTPListParseEngine;

/**
 * A functional test suite for checking that site listings work.
 */
@Disabled
public class ListingFunctionalTest {

    private static FTPClient client;
    private static final String hostName = "ftp.ibiblio.org";
    private static final String validParserKey = "unix";
    private static final String invalidParserKey = "vms";
    private static final String validFilename = "javaio.jar";
    private static final String validPath = "pub/languages/java/javafaq";
    private static final String pwdPath = "/pub/languages/java/javafaq";

    @BeforeAll
    public static void setUp() throws Exception {
        client = new FTPClient();
        client.connect(hostName);
        client.login("anonymous", "anonymous");
        client.enterLocalPassiveMode();
    }

    @AfterAll
    public static void tearDown() throws Exception {
        client.logout();
        if (client.isConnected()) {
            client.disconnect();
        }
        client = null;
    }

    @Test
    public void testInitiateListParsing() throws IOException {
        client.changeWorkingDirectory(validPath);
        FTPListParseEngine engine = client.initiateListParsing();
        List<FTPFile> files = Arrays.asList(engine.getNext(25));
        assertTrue(findByName(files, validFilename), files.toString());
    }

    @Test
    public void testInitiateListParsingWithPath() throws IOException {
        FTPListParseEngine engine = client.initiateListParsing(validParserKey, validPath);
        List<FTPFile> files = Arrays.asList(engine.getNext(25));
        assertTrue(findByName(files, validFilename), files.toString());
    }

    @Test
    public void testInitiateListParsingWithPathAndAutodetection() throws IOException {
        FTPListParseEngine engine = client.initiateListParsing(validPath);
        List<FTPFile> files = Arrays.asList(engine.getNext(25));
        assertTrue(findByName(files, validFilename), files.toString());
    }

    @Test
    public void testListFiles() throws IOException {
        FTPClientConfig config = new FTPClientConfig(validParserKey);
        client.configure(config);
        List<FTPFile> files = Arrays.asList(client.listFiles(validPath));
        assertTrue(findByName(files, validFilename), files.toString());
    }

    @Test
    public void testListFilesWithAutodection() throws IOException {
        client.changeWorkingDirectory(validPath);
        List<FTPFile> files = Arrays.asList(client.listFiles());
        assertTrue(findByName(files, validFilename), files.toString());
    }

    @Test
    public void testListFilesWithIncorrectParser() throws IOException {
        FTPClientConfig config = new FTPClientConfig(invalidParserKey);
        client.configure(config);
        FTPFile[] files = client.listFiles(validPath);
        assertNotNull(files);
        assertTrue(Arrays.equals(new FTPFile[]{}, files), "Expected empty array: " + Arrays.toString(files));
    }

    @Test
    public void testListFilesWithPathAndAutodetection() throws IOException {
        List<FTPFile> files = Arrays.asList(client.listFiles(validPath));
        assertTrue(findByName(files, validFilename), files.toString());
    }

    @Test
    public void testListNames() throws IOException {
        client.changeWorkingDirectory(validPath);
        String[] names = client.listNames();
        assertNotNull(names);
        List<String> lnames = Arrays.asList(names);
        assertTrue(lnames.contains(validFilename), lnames.toString());
    }

    @Test
    public void testListNamesWithPath() throws IOException {
        String[] listNames = client.listNames(validPath);
        assertNotNull(listNames, "listNames not null");
        List<String> names = Arrays.asList(listNames);
        assertTrue(findByName(names, validFilename), names.toString());
    }

    @Test
    public void testPrintWorkingDirectory() throws IOException {
        client.changeWorkingDirectory(validPath);
        String pwd = client.printWorkingDirectory();
        assertEquals(pwdPath, pwd);
    }


    private boolean findByName(List<?> fileList, String string) {
        boolean found = false;
        Iterator<?> iter = fileList.iterator();
        while (iter.hasNext() && !found) {
            Object element = iter.next();
            if (element instanceof FTPFile) {
                FTPFile file = (FTPFile) element;
                found = file.getName().equals(string);
            } else {
                String filename = (String) element;
                found = filename.endsWith(string);
            }
        }
        return found;
    }
}
