class SshFileRequestor(object):
    """
    Helper class for retrieving files from remote server
    """
    _host = None
    _username = None
    _password = None
    _pkey = None
    _keyfile = None

    _path = None
    _size = None
    _start = 0
    
    _ssh = None
    _client = None
    _keepalive = None

    def __init__(self, host, username=None, password=None, pkey=None, key_filename=None, path=None, keep_alive=True):
        """
        Constructor for class 

            @param host: remote hostname
            @param username : login username
            @param password : login password
            @param pkey : private key used for login
            @param key_filename : key file used for login
            @param path : file path to be retrieved
            @param keep_alive : establish only one connection

        """
        self._host = host
        self._username = username
        self._password = password
        self._pkey = pkey
        self._keyfile = key_filename
        self._path = path
        self._keepalive = keep_alive
        self.ssh_connect()

    def __del__(self):
        """
        Destructor for class
        """
        self.ssh_disconnect()
        
    def ssh_connect(self):
        """
        Establish ssh connection
        """
        if not self._ssh or not self._keepalive:
            self._ssh = paramiko.SSHClient()
            self._ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            self._ssh.connect(hostname=self._host, username=self._username, password=self._password, pkey=self._pkey, key_filename=self._keyfile)

    def ssh_disconnect(self):
        """
        Destroy ssh connection
        """
        if self._client:
            self._client.close()
            self._client = None
        if self._ssh:
            self._ssh.close()
            self._ssh = None

    def remote_tail(self, remote_host, path=None, length=0):
        """
        Tail the file from a remote host (current connection used for hop purpose):
        Please make sure the new ssh remote login does not require to input credentials
            
        @param remote_host: target server where the file is located 
        @param path: path to file on the target server
        @param length: length used for tailing

        @return: a list of last n lines of file
        """
        if path :
            self._path = path
        # make sure there's a connection
        self.ssh_connect()
        std_in, std_out, std_err = self._ssh.exec_command('ssh -t %s tail -%i %s' % (remote_host, length, self._path))
        lines = std_out.read().strip().split('\n')
        return lines[-length:] if len(lines) > length else lines[1:]


    def tail(self, path=None, length=0):
        """
        Tail a file on the server

        @param path: path to file on the server
        @param length: length used for tailing, tailing from last position (or beginning) if length is not provided

        @return: a list of last n lines of file
        """
        if path:
            self._path = path
        if not self._client:
            # make sure there's a connection
            self.ssh_connect()
            self._client = self._ssh.open_sftp()

        fstat = self._client.stat(self._path)
        if length > 0:
            #we assume that each line may contains MAX_CHARS_IN_ONE_LINE characters at max
            self._start = max(0,  fstat.st_size - (MAX_CHARS_IN_ONE_LINE * length))
        with self._client.open(self._path, 'r') as f:
            # check if we have the file size
            f.seek(self._start)
            lines = f.read().strip().split('\n')
        
        self._start = fstat.st_size

        return lines[-length:] if len(lines) > length else lines[1:]

