# Copyright (C) 2005 JanRain, Inc.
# Copyright (C) 2009, 2010 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import time
import urlparse

from apache_openid import logging
from apache_openid.utils import add_cookie, get_cookies


class Request(object):
    auto_login_lifetime = 24 * 60 * 60 * 365

    def __init__(self, request, action_path, session):
        self.request = request
        self.action_path = action_path
        self.session = session

    def action_url(self, action):
        """Generate a URL that performs the given action. This depends on
        knowing where the actions live.
        """
        action_path = self.action_path
        if action_path.endswith('/'):
            action_path = action_path[:-1]
        return urlparse.urljoin(self.server_url, action_path) + "/+" + action

    def _get_cookied_user(self):
        user = self.session.get('cookied_user')
        logging.debug("Getting cookied user: %s", user)
        return user

    def _set_cookied_user(self, openid_identifier):
        logging.debug("Setting cookied user to %s", openid_identifier)
        self.session['cookied_user'] = openid_identifier

    def _del_cookied_user(self):
        del self.session['cookied_user']

    def _get_last_user(self):
        cookies = get_cookies(self.request)
        cookie = cookies.get('mpopenid.last_user')
        if cookie is None:
            logging.debug('No last user')
            return None
        logging.debug('Got last user: %r', cookie.value)
        return cookie.value

    def _set_last_user(self, username):
        assert isinstance(username, basestring)
        expires = time.time() + self.auto_login_lifetime
        add_cookie(self.request,
            'mpopenid.last_user', username, expires=expires)
        logging.debug('Set last user: %r', username)

    def _del_last_user(self):
        add_cookie(self.request, 'mpopenid.last_user', '', expires=0)
        logging.debug('Deleted last user')

    @property
    def uri(self):
        # request.request_uri and unparsed_uri
        # this may not always be giving the correct value!
        # Seems to miss the "/openid/" prefix when called
        # inside a <Location /openid/> directive.
        # The value in subprocess_env seems correct.
        #return urlparse.urljoin(self.server_url, self.request.unparsed_uri)
        request_url = self.request.subprocess_env['REQUEST_URI']
        request_url = request_url.split('?')
        return urlparse.urljoin(self.server_url, request_url[0])

    @property
    def action(self):
        action = self.uri.split('/').pop()
        logging.debug("Looking for %s", action)
        if action in ['+login', '+logout', '+return']:#self.handler.known_actions:
            logging.debug("Action %s found in URL %s", action, self.uri)
            return action
        else:
            return None

    @property
    def server_url(self):
        """Return the root URL of the server that is serving this request."""
        host = self.request.hostname
        port = self.request.connection.local_addr[1]

        # Don't include the default port number in the URL
        if self.request.is_https():
            default_port = 443
            proto = 'https'
        else:
            default_port = 80
            proto = 'http'

        if port == default_port:
            return '%s://%s/' % (proto, host)
        else:
            return '%s://%s:%s/' % (proto, host, port)

    def __getattribute__(self, name):
        if name in ['cookied_user', 'last_user']:
            return object.__getattribute__(self, '_get_%s' % name)()
        else:
            try:
                request = object.__getattribute__(self, 'request')
                if name.startswith('__') or name in dir(self):
                    raise AttributeError
                else:
                    return request.__getattribute__(name)
            except AttributeError:
                return object.__getattribute__(self, name)

    def __setattr__(self, name, value):
        if name in ['request', 'action_path', 'session']:
            object.__getattribute__(self, '__dict__')[name] = value
        elif name in ['cookied_user', 'last_user']:
            object.__getattribute__(self, '_set_%s' % name)(value)
        else:
            try:
                request = object.__getattribute__(self, 'request')
                if name.startswith('__') or name in dir(self):
                    raise AttributeError
                else:
                    request.__setattr__(name, value)
            except AttributeError:
                object.__getattribute__(self, '__dict__')[name] = value

    def __delattr__(self, name):
        if name in ['cookied_user', 'last_user']:
            object.__getattribute__(self, '_del_%s' % name)()
