package com.jscape.filetransfer;

import com.jscape.inet.vfs.PathSystem;

import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

import static com.jscape.util.Parameters.assertNotNull;

/**
 * @author Alex Usun
 */
public class RecursiveFileListOperation
        implements FileTransferOperation {

    private final String remoteDirectory;
    private FileTransfer transfer;
    private List<FileTransferRemoteFile> files;

    public RecursiveFileListOperation(String remoteDirectory) {
        assertNotNull(remoteDirectory);
        this.remoteDirectory = remoteDirectory;
    }

    @Override
    public RecursiveFileListOperation applyTo(FileTransfer transfer)
            throws FileTransferException {
        assertNotNull(transfer);
        this.transfer = transfer;

        initTransfer();
        this.files = new LinkedList<>();
        listRecursive(this.remoteDirectory);

        return this;
    }

    public List<FileTransferRemoteFile> files() {
        return this.files;
    }

    private void initTransfer()
            throws FileTransferException {
        if (!this.transfer.isConnected()) {
            this.transfer.connect();
        }
    }

    private void listRecursive(String remoteDirectory)
            throws FileTransferException {
        String currentDirectory = this.transfer.getDir();
        this.transfer.setDir(remoteDirectory);

        try {
            Enumeration entries = this.transfer.getDirListing();

            while (entries.hasMoreElements()) {
                FileTransferRemoteFile entry = (FileTransferRemoteFile) entries.nextElement();
                String filename = entry.getFilename();

                if (entry.isDirectory() && (FileTransfer.PARENT_DIRECTORY.equals(filename) || FileTransfer.CURRENT_DIRECTORY.equals(filename))) {
                    continue;
                }

                if (entry.isDirectory()) {
                    listRecursive(filename);
                } else {
                    entry.setFilename(PathSystem.resolve(this.transfer.getDir(), entry.getFilename()));
                    this.files.add(entry);
                }
            }
        } catch (FileTransferException e) {
            // ignore: possible permission issues
        } finally {
            this.transfer.setDir(currentDirectory);
        }
    }
}
