import elementtree.ElementTree as ET
import urllib, mechanize
from datetime import datetime
from decimal import Decimal
import md5

# -*- coding: iso-8859-15 -*-
""" Clase para comunicarse con DivShare basado en http://www.divshare.com/integrate/api"""

API_URL = 'http://www.divshare.com/api/'

class DivShareFile:
    id=None
    name=""
    description=""
    size=Decimal("0.0")
    downloads=0
    last_download=None
    uploadDate=None
    folderName=""
    folderId=0

    def __str__( self):
        return "%s - Id:%s" % (self.name,self.id)

class DivShareFolder:
    id=None
    name=""

    def __str__( self):
        return "%s - Id:%s" % (self.name,self.id)

class DivShareApi:
    def __init__(self,key, secret, session_key=''):
        self.key = key
        self.secret = secret
        self.session_key = session_key
        self.IsLogged = False
        self._lastXml = None
        
    def get_last_response(self):
        '''
        For debugging. Use ET.dump(xml) to print it
        '''
        return self._lastXml


    def _create_signature(self,params):
        '''
        Encode the signature for api calls
        '''
        #Must be alphabetical
        keys = params.keys()
        keys.sort()
        
        signature = self.secret+self.session_key
        
        for key in keys:
            if not(key in 'api_key, api_session_key, method, api_sig'):
                if params[key]<>None:
                    signature = signature + "%s%s" % (key,params[key])
        
        return md5.new(signature).hexdigest()

    def _get_files(self,xml):
        '''
        Get the files in a nice list
        '''
        files = []
        
        for file in xml.getiterator("file"):
            theFile = DivShareFile()
            
            theFile.id =  file.find('file_id').text
            theFile.name = file.find('file_name').text
            theFile.description = file.find('file_description').text
            theFile.size = Decimal(file.find('file_size').text)
            
            theFile.downloads = int(file.find('downloads').text)
            theFile.last_download = datetime.utcfromtimestamp(int(file.find('last_downloaded_at').text))
            theFile.uploadDate = datetime.utcfromtimestamp(int(file.find('uploaded_at').text))
            
            theFile.folderName = file.find('folder_title').text
            theFile.folderId = int(file.find('folder_id').text)
            
            files.append(theFile)
        
        return files
    
    def  _postData(self,method,TheParams={}):
        '''
        POST the data and get the info back.
        '''
        br = mechanize.Browser()
        
        api_id=""
        
        params={}
        
        for key,value in TheParams.iteritems():
            if value<>None:
                params[key]=value

        params['api_key'] = self.key
        params['method'] = method
        
        if self.IsLogged:
            #This must not be urlencode...
            api_id = 'api_session_key=' + self.session_key + '&api_sig=' + self._create_signature(params)+'&'

        data = api_id + urllib.urlencode(params)
        
        self._lastXml = br.open(API_URL, data)
        
        xml =  ET.parse(self._lastXml)
        
        #Informar de inmediato de los errores internos
        if xml.find('error')<>None:
            raise xml.find('error').text
        
        return xml
    
    def login(self,email,pwd):
        '''
        Logs in, and sets the api_session_key for internal use.
        '''

        res = self._postData('login',{'user_email': email,'user_password':pwd})
        
        api_key = res.find('api_session_key')
        
        if api_key is None:
            raise res.find('error').text
        else:
            self.session_key = api_key.text
            self.IsLogged = True

        return self.session_key 
    
    def logout(self):
        '''Logged out on successs, and deletes the current session key'''
        res = self._postData('logout')
        self.session_key=None
        

    def get_user_files(self,limit=50,offset=0):
        '''
        Gets all the files assigned to the logged in user
        limit sets the max number of files returned
        Use offset for pagination -- for example, page 2 has an offset of 10 and a limit of 10
        '''
        
        return self._get_files(self._postData('get_user_files',{'limit':limit,'offset':offset}))
    
    def get_folder_files(self,folder_id,limit=50,offset=0):
        '''
        Gets all the files in a folder owned by the logged in user
        '''
        return self._get_files(self._postData('get_folder_files',{'folder_id':folder_id,'limit':limit,'offset':offset}))

    def get_user_info(self):
        '''
        Gets user e-mail and first name. May add more info to this response in the future.
        '''
        xml = self._postData('get_user_info').find("user_info")
        
        return {'userName':xml.find('user_fname').text,'userMail':xml.find('user_email').text}
    
    def get_upload_ticket(self):
        '''
        Returns an upload ticket, which must then be inserted into the upload form.
        '''
        xml = self._postData('get_upload_ticket').find("upload_ticket")
        
        return xml.text

if __name__ == '__main__':
    divShare = DivShareApi('YOUR-KEY','YOUR-SECRET')
    
    print "Loging...."
    
    print divShare.login('mamcx@elmalabarista.com','pinkycerebro')
    
    print "Get all files..."
    files =divShare.get_user_files()
    for file in files:
        print file
    
    print "Get files of a folder..."
    files =divShare.get_folder_files(203635)
    for file in files:
        print file
    
    print "New upload ticket..."
    print divShare.get_upload_ticket()
    
    print "User info..."
    print divShare.get_user_info()
    
    print "Logout"
    divShare.logout()