import os
import urlparse
import boto
import boto.connection
import boto.jsonresponse
import boto.exception
import awsqueryrequest

class NoCredentialsError(boto.exception.BotoClientError):

    def __init__(self):
        s = 'Unable to find credentials'
        super(NoCredentialsError, self).__init__(s)

class AWSQueryService(boto.connection.AWSQueryConnection):

    Name = ''
    Description = ''
    APIVersion = ''
    Authentication = 'sign-v2'
    Path = '/'
    Port = 443
    Provider = 'aws'
    EnvURL = 'AWS_URL'

    Regions = []

    def __init__(self, **args):
        self.args = args
        self.check_for_credential_file()
        self.check_for_env_url()
        if 'host' not in self.args:
            if self.Regions:
                region_name = self.args.get('region_name',
                                            self.Regions[0]['name'])
                for region in self.Regions:
                    if region['name'] == region_name:
                        self.args['host'] = region['endpoint']
        if 'path' not in self.args:
            self.args['path'] = self.Path
        if 'port' not in self.args:
            self.args['port'] = self.Port
        try:
            super(AWSQueryService, self).__init__(**self.args)
            self.aws_response = None
        except boto.exception.NoAuthHandlerFound:
            raise NoCredentialsError()

    def check_for_credential_file(self):
        """
        Checks for the existence of an AWS credential file.
        If the environment variable AWS_CREDENTIAL_FILE is
        set and points to a file, that file will be read and
        will be searched credentials.
        Note that if credentials have been explicitelypassed
        into the class constructor, those values always take
        precedence.
        """
        if 'AWS_CREDENTIAL_FILE' in os.environ:
            path = os.environ['AWS_CREDENTIAL_FILE']
            path = os.path.expanduser(path)
            path = os.path.expandvars(path)
            if os.path.isfile(path):
                fp = open(path)
                lines = fp.readlines()
                fp.close()
                for line in lines:
                    if line[0] != '#':
                        if '=' in line:
                            name, value = line.split('=', 1)
                            if name.strip() == 'AWSAccessKeyId':
                                if 'aws_access_key_id' not in self.args:
                                    value = value.strip()
                                    self.args['aws_access_key_id'] = value
                            elif name.strip() == 'AWSSecretKey':
                                if 'aws_secret_access_key' not in self.args:
                                    value = value.strip()
                                    self.args['aws_secret_access_key'] = value
            else:
                print 'Warning: unable to read AWS_CREDENTIAL_FILE'

    def check_for_env_url(self):
        """
        First checks to see if a url argument was explicitly passed
        in.  If so, that will be used.  If not, it checks for the
        existence of the environment variable specified in ENV_URL.
        If this is set, it should contain a fully qualified URL to the
        service you want to use.
        Note that any values passed explicitly to the class constructor
        will take precedence.
        """
        url = self.args.get('url', None)
        if url:
            del self.args['url']
        if not url and self.EnvURL in os.environ:
            url = os.environ[self.EnvURL]
        if url:
            rslt = urlparse.urlparse(url)
            if 'is_secure' not in self.args:
                if rslt.scheme == 'https':
                    self.args['is_secure'] = True
                else:
                    self.args['is_secure'] = False

            host = rslt.netloc
            port = None
            l = host.split(':')
            if len(l) > 1:
                host = l[0]
                port = int(l[1])
            if 'host' not in self.args:
                self.args['host'] = host
            if port and 'port' not in self.args:
                self.args['port'] = port

            if rslt.path and 'path' not in self.args:
                self.args['path'] = rslt.path

    def _required_auth_capability(self):
        return [self.Authentication]

