from BeautifulSoup import BeautifulSoup
import urllib
import httplib

GDATA_URL = '/accounts/ClientLogin'

class GdataError(Exception):
    pass

class Gdata:
    """
    A class to retrieve a users contacts from their Google Account.
    
    Dependencies:
    -------------
    * BeautifulSoup. 
    * That's it. :-)

    Usage:
    ------
    >>> g = Gdata('email@example.org', 'password')
    >>> g.login()
    (200, 'OK')
    >>> g.get_contacts()
    >>> g.contacts
    [(u'Persons Name', 'name@person.com'), ...]


    """
    def __init__(self, username='test@gmail.com', password='test', service='cp'):
        self.username = username
        self.password = password
        self.account_type = 'HOSTED_OR_GOOGLE'  # Allow both Google Domain and Gmail accounts
        self.service = service                  # Defaults to cp (contacts)
        self.source = 'google-data-import'            # Our application name
        self.code = ''                          # Empty by default, populated by self.login()
        self.contacts = []                      # Empty list by default, populated by self.get_contacts()
    
    def login(self):
        """
        Login to Google. No arguments.
        """
        data = urllib.urlencode({
            'accountType': self.account_type,
            'Email': self.username,
            'Passwd': self.password,
            'service': self.service,
            'source': self.source
        })
        headers = {
            'Content-type': 'application/x-www-form-urlencoded',
            'Accept': 'text/plain'
        }
        
        conn = httplib.HTTPSConnection('google.com')
        conn.request('POST', GDATA_URL, data, headers)
        response = conn.getresponse()
        if not str(response.status) == '200':
            raise GdataError("Couldn't log in. HTTP Code: %s, %s" % (response.status, response.reason))
            
        d = response.read()
        
        self.code = d.split("\n")[2].replace('Auth=', '')
        return response.status, response.reason
    
    def _request(self, max_results=200):
        """
        Base function for requesting the contacts. We'll allow other methods eventually
        """
        url = '/m8/feeds/contacts/%s/base/?max-results=%d' % (self.username, max_results)
        
        headers = {'Authorization': 'GoogleLogin auth=%s' % self.code}
        
        conn = httplib.HTTPConnection('www.google.com')
        conn.request('GET', url, headers=headers)
        response = conn.getresponse()
        if not str(response.status) == '200':
            raise GdataError("Couldn't log in. HTTP Code: %s, %s" % (response.status, response.reason))
        
        return response.read()
    
    def get_contacts(self, max_results=200):
        """ Parses the contacts (using BeautifulSoup) from self._request, and then populates self.contacts
        """
        soup = BeautifulSoup(self._request(max_results))
        self.contacts = []
        for entry in soup.findAll('title'):
            if len(entry.parent.findAll(['gd:email', 'title'])) == 2:
                s = entry.parent.findAll(['gd:email', 'title'])
                self.contacts.append((s[0].string, s[1].get('address')))
        
        return