#!/usr/bin/env python

import os
import urllib
import json
import getpass

from dm.common.utility.encoder import Encoder
from dm.common.exceptions.dmException import DmException
from dm.common.exceptions.invalidRequest import InvalidRequest
from dm.common.objects.fileMetadata import FileMetadata
from dm.common.objects.directoryMetadata import DirectoryMetadata
from dm.common.objects.experiment import Experiment
from dm.common.utility.rsyncFileTransfer import RsyncFileTransfer
from dsRestApi import DsRestApi

class FileRestApi(DsRestApi):
    
    def __init__(self, username=None, password=None, host=None, port=None, protocol=None):
        DsRestApi.__init__(self, username, password, host, port, protocol)

    @DsRestApi.execute
    def processFile(self, experimentFilePath, experimentName, fileInfo={}):
        url = '%s/files/processFile' % (self.getContextRoot())
        if not experimentFilePath:
            raise InvalidRequest('Experiment file path must be provided.')
        if not experimentName:
            raise InvalidRequest('Experiment name must be provided.')
        fileInfo['experimentFilePath'] = experimentFilePath
        fileInfo['experimentName'] = experimentName
        url += '?fileInfo=%s' % (Encoder.encode(json.dumps(fileInfo)))
        responseDict = self.sendSessionRequest(url=url, method='POST')
        return FileMetadata(responseDict)

    @DsRestApi.execute
    def statFile(self, experimentFilePath, experimentName, fileInfo={}):
        url = '%s/files/statFile' % (self.getContextRoot())
        if not experimentFilePath:
            raise InvalidRequest('Experiment file path must be provided.')
        if not experimentName:
            raise InvalidRequest('Experiment name must be provided.')
        fileInfo['experimentFilePath'] = experimentFilePath
        fileInfo['experimentName'] = experimentName
        url += '?fileInfo=%s' % (Encoder.encode(json.dumps(fileInfo)))
        responseDict = self.sendSessionRequest(url=url, method='POST')
        return FileMetadata(responseDict)

    @DsRestApi.execute
    def processDirectory(self, experimentDirectoryPath, experimentName, directoryInfo={}):
        url = '%s/files/processDirectory' % (self.getContextRoot())
        if not experimentName:
            raise InvalidRequest('Experiment name must be provided.')
        directoryInfo['experimentDirectoryPath'] = experimentDirectoryPath
        directoryInfo['experimentName'] = experimentName
        url += '?directoryInfo=%s' % (Encoder.encode(json.dumps(directoryInfo)))
        responseDict = self.sendSessionRequest(url=url, method='POST')
        return DirectoryMetadata(responseDict)

    @DsRestApi.execute
    def download(self, experimentName, experimentFilePath='',  destDirectory='.'):
        username = getpass.getuser()

        # Initialize download
        url = '%s/downloadAuthorizations/%s/%s' % (self.getContextRoot(), username, experimentName)
        if not experimentName:
            raise InvalidRequest('Experiment name must be provided.')
        self.logger.info('Authorizing download for user %s (experiment: %s)' % (username, experimentName))
        responseDict = self.sendSessionRequest(url=url, method='POST')
        experiment = Experiment(responseDict)

        # Download
        try:
            storageDirectory = experiment.get('storageDirectory')
            storageHost = experiment.get('storageHost')
            src = '%s@%s:%s' % (username, storageHost, storageDirectory)
            if experimentFilePath:
                src = '%s/%s' % (src, experimentFilePath)
            dest = destDirectory
            
            rsyncPath = '/tmp/rsync.%s.%s' % (username, experimentName)
            flags = '-arvlP --rsync-path="%s"' % rsyncPath
            fileTransfer = RsyncFileTransfer(src=src, dest=dest, flags=flags)
            self.logger.info('Executing file download on behalf of %s (experiment: %s)' % (username, experimentName))
            fileTransfer.execute()
        finally:
            # Finalize download
            self.logger.info('Deleting download authorization for user %s (experiment: %s)' % (username, experimentName))
            self.sendSessionRequest(url=url, method='DELETE')

#######################################################################
# Testing.

if __name__ == '__main__':
    api = FileRestApi('sveseli', 'sveseli', 'zagreb.svdev.net', 22236, 'http')
    print api.processFile('file1', '/ESAF/exp1', 'exp1')