import sys
import random

from quixote import get_publisher, get_response, redirect, get_request
from quixote.directory import Directory
from quixote.errors import TraversalError

import admin
import liberty
import saml2
import httplib
import urllib

from qommon.form import *

import errors
import logger
import misc
import template
import emails

from users import User
from hosts import Host


class LibertySite(Directory):

    _q_exports = ['', 'login', 'logout', 'liberty']
    
    liberty = liberty.Liberty()

    def __init__(self, component):
        self.name = component

    def _q_index (self):
        raise errors.TraversalError()

    def login [html] (self):
        logger.info('login')
        host = Host.get_host_from_url()
        if host is None:
            return template.error_page(_('SSO support is not yet configured'))
#        idps = host.idps
        misc.reload_cfg()

#       if len(idps) == 0:
        if not misc.cfg.has_key('idp'):
            return template.error_page(_('SSO support is not yet configured'))

#        if len(idps) == 1:
        else:
            # if there is only one visible IdP, perform login automatically on
            # this one.
            server = misc.get_lasso_server('liberty')
            if server is None:
                return template.error_page(_('SSO support is not yet configured'))
            for x in server.providerIds:
                key_provider_id = x.replace(str('://'), str('-')).replace(str('/'), str('-'))
                return self.liberty.perform_login(x)

            server = misc.get_lasso_server('saml2')
            for x in server.providerIds:
                key_provider_id = x.replace(str('://'), str('-')).replace(str('/'), str('-'))
                return self.saml.perform_login(x)

        return template.error_page("Can't use several Identity Providers for one Service Provider at the moment")

        form = Form(enctype='multipart/form-data')
        options = []
        # XXX: use intro cookie to get preferred value
        value = None
        providers = {}
        for kidp, idp in misc.cfg.get('idp', {}).items():
            if idp.get('hide'):
                continue
            p = lasso.Provider(lasso.PROVIDER_ROLE_IDP,
                    misc.get_abs_path(idp['metadata']),
                    misc.get_abs_path(idp['publickey']), None)
            providers[p.providerId] = p

        include_protocol = True
        if len([x for x in providers.values() if 
                x.getProtocolConformance() == lasso.PROTOCOL_SAML_2_0]) in (0, len(providers)):
            include_protocol = False

        for p in providers.values():
            label = misc.get_provider_label(p)
            if include_protocol:
                if p.getProtocolConformance() == lasso.PROTOCOL_SAML_2_0:
                    label = '%s (SAML 2.0)' % label
                else:
                    label = '%s (Liberty ID-FF 1.2)' % label
            options.append((p.providerId, label))
            if not value:
                value = p.providerId
        form.add(RadiobuttonsWidget, 'idp', value = value, options = options, delim = '<br/>')
        form.add_submit('submit', _('Submit'))

        if form.is_submitted() and not form.has_errors():
            idp = form.get_widget('idp').parse()
            p = providers[form.get_widget('idp').parse()]
            if p.getProtocolConformance() == lasso.PROTOCOL_SAML_2_0:
                return self.saml.perform_login(idp)
            else:
                return self.liberty.perform_login(idp)

        template.html_top(_('Login'))
        '<p>%s</p>' % _('Select the identity provider you want to use.')
        form.render()

    def logout(self):
        logger.info('logout')
        session = get_session()
        if not session:
            return redirect('%s/' % get_request().environ['SCRIPT_NAME'])
        # add settings to disable single logout?
        #   (and to set it as none/get/soap?)
        return self.liberty.singleLogout()

#     def defederate(self):
#         logger.info('defederate')
#         session = get_session()
#         if not session:
#             return redirect('/')
#         host = Host.get_host_from_url()
#         if host is None:
#             return template.error_page(_('SSO support is not yet configured'))
# #        idps = host.idps
#         misc.reload_cfg()

# #       if len(idps) == 0:
#         if not misc.cfg.has_key('idp'):
#             return template.error_page(_('SSO support is not yet configured'))

# #        if len(idps) == 1:
#         else:
#             # if there is only one visible IdP, perform login automatically on
#             # this one.
#             server = misc.get_lasso_server('liberty')
#             if server is None:
#                 # Get a templated page instead
#                 return template.error_page(_('SSO support is not yet configured'))
#             for x in server.providerIds:
#                 key_provider_id = x.replace(str('://'), str('-')).replace(str('/'), str('-'))
#                 return self.liberty.defederate(x)

#     def admin_token [html] (self):
#         request = get_request()
#         user_name = request.get_field('id')
#     
#         form = Form(enctype="multipart/form-data", use_tokens = False)
#         form.add_submit("submit", _("Generate"))
#         form.add_submit("cancel", _("Cancel"))

#         del get_response().breadcrumb

#         if not form.is_submitted() or form.has_errors():
#             template.html_top(_('Identification Token'))
#             '<p>User %s has no token yet</p>' % user_name
#             form.render()
#         else:
#             if request.form.has_key('submit'):
#                 template.html_top(_('Identification Token'))
#                 token = '-'.join(['%04d' % random.randint(1, 9999) for x in range(4)])

#                 # Save token on disk
#                 if user_name is not None:
#                     token_dir = str(os.path.join(misc.get_proxied_site_path(), 'tokens'))
#                     if not os.path.isdir(token_dir):
#                         os.mkdir(token_dir)
#                     token_file_name = str(os.path.join(token_dir, token))
#                     if not os.path.isfile(token_file_name):
#                         token_file = open(token_file_name, str('w'))
#                         token_file.write(user_name)
#                         token_file.close()

#                 "<p>"
#                 _('Identification Token for %s :') % user_name
#                 " %s</p>" % token

#                 form = Form(enctype="multipart/form-data", use_tokens = False)
#                 form.add_string('email', title = _('Email'))
#                 form.add_hidden('token', value = token)
#                 form.add_submit('send', _('Send it by email'))
#                 form.add_submit('back', _('Back'))
#                 form.render()
#             else:
#                 if request.form.has_key('send'):
#                     token = request.get_field('token')
#                     email = request.get_field('email')
#                     site_url = '%s://%s/liberty/%s/token?token=%s' \
#                         % (request.get_scheme(), request.get_server(), misc.get_proxied_site_name(), token)
#                     body = _("""You have been given an identification token.

# Your token is %s.

# Click here to use it : %s

# """) % (token, site_url)
#                     emails.email(_('Identification Token'), body, email)
#                 return redirect(misc.get_site_root_url())


#     def admin_new_user(self):
#         host = Host.get_host_from_url()
#         if host is None or not hasattr(host, 'admin_new_user_url'):
#             return

#         request = get_request()
#         session = get_session()
#         
#         fields = request.get_fields() 

#         # Should test email as well
#         if fields['user_id'] == '' or fields['user_nom'] == '':
#             redirect(host.admin_new_user_url)

#         user_id = fields['user_id']
#         user_email = fields['user_email']
#         password = '-'.join(['%04d' % random.randint(1, 9999) for x in range(4)])
#         fields['user_pwd'] = password

#         if self.admin_new_user_post(fields, host.admin_new_user_url) != 302:
#             return redirect(host.admin_new_user_url)

#         token = '-'.join(['%04d' % random.randint(1, 9999) for x in range(4)])
#         
#         # Save token on disk
#         token_dir = str(os.path.join(misc.get_proxied_site_path(), 'tokens'))
#         if not os.path.isdir(token_dir):
#             os.mkdir(token_dir)
#         token_file_name = str(os.path.join(token_dir, token))
#         if not os.path.isfile(token_file_name):
#             token_file = open(token_file_name, str('w'))
#             token_file.write(user_id + '\n')
#             token_file.write(password + '\n')
#             if user_email != '':
#                 token_file.write(user_email)
#             token_file.close()
#             
#         # Send it by email
#         site_url = '%s://%s/liberty/%s/token?token=%s' \
#                     % (request.get_scheme(), request.get_server(), misc.get_proxied_site_name(), token)
#         body = _("""You have been given an identification token.

# Your token is %s.

# Click here to use it : %s

# """) % (token, site_url)
#         emails.email(_('Identification Token'), body, user_email)            

#         return redirect(host.admin_new_user_return_url)

#     def admin_new_user_post(self, fields, url):
#         if url.startswith('http://'):
#             host, query = urllib.splithost(url[5:])
#             conn = httplib.HTTPConnection(host)
#         else:
#             host, query = urllib.splithost(url[6:])
#             conn = httplib.HTTPSConnection(host)
#         body = urllib.urlencode(fields)
#         conn.request('POST', query, body, {'Content-Type': 'application/x-www-form-urlencoded', 'Cookie': 'dc_admin=a%3A3%3A%7Bs%3A7%3A%22user_id%22%3Bs%3A7%3A%22heretik%22%3Bs%3A8%3A%22user_pwd%22%3Bs%3A32%3A%22cc414bfc9c00475b59c87595299ff31d%22%3Bs%3A8%3A%22remember%22%3Bb%3A0%3B%7D'})
#         response = conn.getresponse()
#         conn.close()
#         return response.status

#     def token [html] (self):
#         #if not get_request().user:
#         #    raise errors.AccessUnauthorizedError()

#         del get_response().breadcrumb

#         session = get_session()
#         token = get_request().get_field('token')
#         get_session().token = token
#         
#         redirect('/liberty/%s/login' % misc.get_proxied_site_name())

#     def get_user_cookie(self, user_id):
#         host = Host.get_host_from_url()
#         if host is None:
#             return redirect('/')
#         return_url = host.get_return_url()
#         user_dir = misc.get_abs_path(os.path.join(misc.get_proxied_site_path(), 'users'))
#         for user_file_name in os.listdir(user_dir):
#             user_file = open(os.path.join(user_dir, user_file_name), 'r')
#             data = user_file.read().split()
#             user_file.close()
#             # Return cookie
#             if data[0] == user_id:
#                 return data[2]
#         return None
