"""
FTP Stream library.
"""
import ftplib
import io
import threading
import time
import traceback


class FTPStream(object):
    """
    FTP upload for streaming data.
    """
    DEFAULT_POLL_INTERVAL = 10
    DEFAULT_TIMEOUT = 30

    def __init__(self, host, user, password, port=21, directory='.',
                 poll_interval=DEFAULT_POLL_INTERVAL, timeout=DEFAULT_TIMEOUT):
        """
        Constructor.

        Args:
            host (str): FTP server hostname
            user (str): FTP username
            password (str): FTP password
            port (int): FTP port
            directory (str): FTP (remote) directory
            poll_interval (int): poll interval, seconds
            timeout (int): connection timeout, seconds
        """
        self.host = host
        self.user = user
        self.password = password
        self.port = port or 21
        self.directory = directory or '.'
        self.poll_interval = poll_interval
        self.timeout = timeout
        self.queue = []
        self.running = False

    def _upload(self):
        while self.running or self.queue:
            while len(self.queue):
                print 'Queue length:', len(self.queue)
                try:
                    task = self.queue[0]
                    print 'Uploading %s...' % task['file_name']
                    self.ftp = ftplib.FTP(host=self.host, timeout=self.timeout)
                    self.ftp.login(user=self.user, passwd=self.password)
                    self.ftp.set_pasv(True)
                    self.ftp.cwd(self.directory)
                    self.ftp.storbinary('STOR %s' % task['file_name'], task['data'])
                    self.queue.pop(0)
                except:
                    traceback.print_exc()
                    time.sleep(self.poll_interval)
            time.sleep(self.poll_interval)

    def start(self):
        if self.running:
            return
        self.running = True
        upload_thread = threading.Thread(target=self._upload)
        upload_thread.start()

    def enqueue(self, file_name, data):
        """
        Enqueues a task.

        Args:
            file_name (str): target file name
            data (bytes): file data
        """
        self.queue.append({'file_name': file_name, 'data': io.BytesIO(data)})

    def stop_when_complete(self):
        self.running = False

    def stop(self):
        del self.queue[:]
        self.running = False
