#-*- coding: utf-8 -*-
import time,random
import hmac, hashlib, binascii
import logging
import urllib
import cgi


class OAuth(object):
    SERVER='https://api.twitter.com/oauth'
    REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token'
    ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token'
    AUTHORIZATION_URL = 'https://api.twitter.com/oauth/authorize'
    VERSION='1.0'
    SIGNATURE_METHOD='HMAC-SHA1'
    CONSUMER_KEY=''
    CONSUMER_SECRET=''
    TOKEN_KEY=None
    TOKEN_SECRET=None
    NONCE=None
    TIMESTAMP=None
    OAUTH_CALLBACK=None
    OAUTH_VERIFIER=None
    def __init__(self, url, callback=None):
        #raise NotImplementedError
        self.OAUTH_CALLBACK = callback
    def getRequestToken(self):
        signature = self.generate_signature('POST', \
                                            self.REQUEST_TOKEN_URL, \
                                            '', \
                                            self.OAUTH_CALLBACK)
        auth_header=self.generate_request_header(signature)
        return auth_header
    def getAccessToken(self):
        signature = self.generate_signature('POST', \
                                            self.ACCESS_TOKEN_URL, \
                                            '', \
                                            None)
        auth_header=self.generate_token_header(signature)
        return auth_header
    def getAuthHeader(self, method, url, params):
        signature= self.generate_signature(method, \
                                            url, \
                                            params, \
                                            None)
        auth_header=self.generate_auth_header(signature)
        return auth_header
    def generate_timestamp(self):
        """Get seconds since epoch (UTC)."""
        return int(time.time())
    def generate_nonce(self,length=8):
        return ''.join([str(random.randint(0,9)) for i in range(8)])
    def generate_sign_basestring(self, key, raw, hash_method=hashlib.sha1):
        return binascii.b2a_base64(hmac.new(key,raw, hash_method).digest())[:-1]
    def generate_base_string(self, params, oauth_callback=None):
        #parms=urlparse.parse_qs(params, 1)
        key='%s&'%self.CONSUMER_SECRET
        if self.TOKEN_SECRET:
            key +='%s'%self.TOKEN_SECRET
        base_string = ''
        if oauth_callback:
            base_string += 'oauth_callback=%s&'%urllib.quote(oauth_callback,'-._~')
            self.OAUTH_CALLBACK = oauth_callback
        self.NONCE=self.generate_nonce()
        self.TIMESTAMP=self.generate_timestamp()
        base_string += 'oauth_consumer_key=%s&oauth_nonce=%s'%(self.CONSUMER_KEY,self.NONCE)
        if self.TOKEN_KEY:
            base_string += ("&oauth_token=%s"%self.TOKEN_KEY)
        base_string += '&oauth_signature_method=%s&oauth_timestamp=%s'%('HMAC-SHA1', self.TIMESTAMP)
        base_string += '&oauth_version=1.0'
        #logging.debug('base_string = %s'%base_string)
        base_str_dic = cgi.parse_qs(base_string)
        if params:
            params_dic = cgi.parse_qs(params)
            #logging.debug('params_dic = %s'%params_dic)
            base_str_dic.update(params_dic)
        #logging.debug('base_str_dic= %s'%base_str_dic)
        for k,v in base_str_dic.items():
            if isinstance(v, unicode):
                base_str_dic[k] = v.encode('utf8')
        #logging.debug('base_str_dic = %s'%base_str_dic)
        base_string = "&".join(["%s=%s" % (urllib.quote(k, '-._~'), urllib.quote(base_str_dic[k][0],'-._~'))
                                for k in sorted(base_str_dic)])
        #logging.debug('base_string join = %s'%base_string)
        base_string = urllib.quote(base_string, '~.-_')
        #logging.debug('base_string : (sort, urlencode) = %s'%base_string)
        return key, base_string
    def generate_signature(self, http_method, base_url, params, oauth_callback=None):
        key = ""
        base_string = ""
        key, base_string = self.generate_base_string(params, oauth_callback)
        base_string ='%s&%s&'%(http_method.upper(), urllib.quote(base_url, '-._~')) + base_string
        #logging.debug('base_string : (before generate) = %s'%base_string)
        #logging.debug('key : %s'%key)
        signature = self.generate_sign_basestring(key, base_string)
        return signature
    def generate_request_header(self, signature):
        header = 'oauth_nonce="%s",'%self.NONCE
        if self.OAUTH_CALLBACK:
            callback_url = 'oauth_callback="%s",'%urllib.quote(self.OAUTH_CALLBACK,'-._~')
        else:
            callback_url = 'oauth_callback="oob",'
        header += callback_url
        header += 'oauth_signature_method="HMAC-SHA1", '
        header += 'oauth_timestamp="%s",'%self.TIMESTAMP
        header += 'oauth_consumer_key="%s",'%self.CONSUMER_KEY
        header += 'oauth_signature="%s",'%urllib.quote(signature,'-._~')
        header += 'oauth_version="1.0"'
        #logging.debug("request_header: %s"%header)
        return {'Authorization' : 'OAuth %s'%header}
    def generate_token_header(self, signature):
        header = 'oauth_nonce="%s",'%self.NONCE
        header += 'oauth_signature_method="HMAC-SHA1", '
        header += 'oauth_timestamp="%s",'%self.TIMESTAMP
        header += 'oauth_consumer_key="%s",'%self.CONSUMER_KEY
        header += 'oauth_token="%s",'%self.TOKEN_KEY
        header += 'oauth_verifier="%s",'%self.OAUTH_VERIFIER
        header += 'oauth_signature="%s",'%urllib.quote(signature,'-._~')
        header += 'oauth_version="1.0"'
        #logging.debug("token_header: %s"%header)
        return {'Authorization' : 'OAuth %s'%header}
    def generate_auth_header(self,signature):
        header = 'oauth_nonce="%s",'%self.NONCE
        header += 'oauth_signature_method="HMAC-SHA1", '
        header += 'oauth_timestamp="%s",'%self.TIMESTAMP
        header += 'oauth_consumer_key="%s",'%self.CONSUMER_KEY
        header += 'oauth_token="%s",'%self.TOKEN_KEY
        header += 'oauth_signature="%s",'%urllib.quote(signature,'-._~')
        header += 'oauth_version="1.0"'
        #logging.debug("token_header: %s"%header)
        return {'Authorization' : 'OAuth %s'%header}
