"""
$URL: svn+ssh://sting.mems-exchange.org/repos/trunk/DurusWorks/proto/lib/ui/slash.qpy $
$Id: slash.qpy 32785 2010-09-15 22:23:23Z dbinger $
"""
from datetime import datetime
from os.path import join
from pprint import pformat
from proto.ui.forms import FormsDirectory
from proto.ui.qwiki import QwikiDirectory
from qp.fill.directory import Directory, get_crumb_tree
from qp.fill.durus_directory import DurusDirectory
from qp.fill.html import href
from qp.fill.static import StaticFile, StaticDirectory
from qp.pub.common import get_publisher, get_path, get_site
from qp.pub.common import get_request, header, footer, page
from qp.pub.common import get_response
from qp.pub.common import get_session, get_user, redirect
from qp.pub.publish import DurusPublisher, RespondNow


class SitePublisher (DurusPublisher):

    configuration = dict(
        # Host and port of durus server.
        durus_address=('localhost', 7002),
        # Host and port of scgi server.        
        scgi_address=('localhost', 7003),
        # Host and port of SSL service provided by Apache (or other).
        https_address=('', 443),
        # Location of database, log, and pid files.
        var_directory='/www/var',
        )

    def display_exceptions(self):
        return True

    def ensure_signed_in(self):
        self.ensure_signed_in_using_digest()

    def header:xml(self, title, style=None, meta=None, **kwargs):
        '<!DOCTYPE html PUBLIC '
        '"-//W3C//DTD XHTML 1.0 Transitional//EN" '
        '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
        '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'
        '<head>'
        '<link rel="stylesheet" href="%s%s" ' % (
            get_request().get_script_name(), '/all.css')
        '<script src="%s%s"></script>' % (
            get_request().get_script_name(), '/proto.js')
        '<link rel="icon" href="%s%s" ' % (
            get_request().get_script_name(), '/favicon.png')
        'type="image/png" />'
        if meta:
            meta
        '<title>%s</title>' % title
        if style:
            '\n<style media="all" type="text/css">%s</style>' % style
        '</head>'
        '\n<body class="%s">' % get_publisher().get_agent_class()
        '<div class="body_top">'
        '<div style="font-weight:bold">'
        title
        '</div>'
        format_menu()
        '</div>'
        '<div class="body_middle">'

    def footer:xml(self, *args, **kwargs):
        format_sessions()
        '</div>' # body_middle
        '<div class="body_bottom">'
        get_request().get_url()
        if get_user():
            href('%s/sign_out' % get_request().get_script_name(),
                 'Sign %s out.' % get_user().get_id(),
                 style="float:right")
        '</div>'
        href('%s/restricted' % get_request().get_script_name(),
             "Ban %s" % get_request().get_remote_address())
        '</body></html>'

def format_menu:xml():
    try:
        crumb_tree = get_crumb_tree()
    except RespondNow:
        crumb_tree = []
    if crumb_tree:
        ' &gt; '.join([href(menu[0][0], menu[0][1], title=menu[0][2])
                        for menu in crumb_tree[:-1] if menu])
        menu = crumb_tree[-1]
        component = get_path().split(str('/'))[-1]
        selected_path = './' + component
        '<ul style="float:right;list-style:none">'
        for path, crumb, title, css_class in menu:
            style = 'padding:2px'
            if path == selected_path:
                style += ";background:orange"
            else:
                style += ";background:#888"
            '<li class="%s" style="%s">' % (css_class, style)
            href(path, crumb, title=title)
            '</li>'
        '</ul>'

class SiteDirectory (Directory):
    """
    This site demonstrates authentication, sessions, static files, and exception
    reporting.
    """

    def __init__(self):
        self.all_css = StaticFile(
            join(get_site().get_static_directory(), 'all.css'),
            mime_type='text/css',
            cache_time=1)
        self.favicon_png = StaticFile(
            join(get_site().get_static_directory(), 'favicon.png'),
            mime_type="image/png",
            cache_time=300)
        self.favicon_ico = StaticFile(
            join(get_site().get_static_directory(), 'favicon.ico'),
            mime_type="image/x-icon",
            cache_time=300)
        self.proto_js = StaticFile(
            join(get_site().get_static_directory(), 'proto.js'),
            mime_type="text/javascript",
            cache_time=10)
        self.static = StaticDirectory(join(get_site().get_static_directory()),
            list_directory=True)

    def get_exports(self):
        yield ('', 'index', 'Home', 'The Home page of this site.')
        yield ('exception', 'exception', 'Exception',
            'Raise an exception')
        yield ('request', 'request', 'Request', 'View the request')
        yield ('hello', 'hello', 'Hello', 'A simple hello page.')
        yield ('hello_user', 'hello_user', 'Hello User',
            'Authenticate for access. (requires SSL).')
        yield ('all.css', 'all_css', None, None)
        yield ('favicon.png', 'favicon_png', None, None)
        yield ('favicon.ico', 'favicon_ico', None, None)
        yield ('proto.js', 'proto_js', None, None)
        yield ('request_', 'request_', None, None)
        yield ('callback', 'callback', "Callback", "Javascript Callback Demo")
        yield ('sign_out', 'sign_out', None, None)
        yield ('restricted', 'ban', None, None)
        yield ('robots.txt', 'robots', None, None)
        yield ('database', 'database', 'Database', 'Browse Database')
        yield ('forms', 'forms', 'Form Demo', 'Basic Form Demonstration')
        yield ('qwiki', 'qwiki', 'Qwiki', 'A Quickie Wiki')
        yield ('static', 'static', 'Static',
           "The directory in the site package called 'static'.")

    database = DurusDirectory()
    forms = FormsDirectory()
    qwiki = QwikiDirectory()


    def robots:str(self):
        get_response().set_content_type('text/plain', 'utf-8')
        # Directions for robots.
        # Some areas aren't worth crawling
        'User-agent: *\n'
        'Disallow: /restricted\n'

    def ban(self):
        publisher = get_publisher()
        site = publisher.get_site()
        banned = site.get_banned()
        if not banned:
            redirect('.')
        session_cookie = get_request().get_cookie(site.get_name())
        if session_cookie in get_publisher().get_sessions() :
            redirect('.')
        banned_addresses = open(banned, 'a')
        banned_addresses.write(' %s\n' % get_request().get_remote_address())
        banned_addresses.close()
        get_publisher().send_to_administrator(
            'Banned: %s\nTo remove, edit the following file:\n%s\n' % (
            get_request().get_remote_address(),
            banned))
        return page(
            'Banned',
            'You (or your software) is not being friendly to this site. '
            'To protect the site, we are no longer answering you. '
            'If you need to be un-banned, please contact us directly. ')

    def exception(self):
        raise Exception('This is an exception.')

    def sign_out(self):
        get_publisher().sign_out('/')

    def index:xml(self):
        header(get_site().get_name())
        "This is the demo app named 'proto'."
        footer()

    load_time = datetime.utcnow()

    def hello:xml(self):
        header(get_site().get_name())
        "Hello!"
        '<p>Time that this module was loaded: %s</p>' % self.load_time
        footer()

    def hello_user:xml(self):
        get_publisher().ensure_signed_in()
        header(get_site().get_name())
        "Hello %s!" % get_user().get_id()
        footer()

    def callback:xml(self):
        header("callback demo")
        '<span style="border:outset;width:30%" '
        'onclick="'
        "retrieve('request_', '42')"
        '">Send new request</span>'
        '<div id="42"></div>'
        footer()

    def request_:xml(self):
        '<dl class="dict">'
        items = sorted(get_request().__dict__.items())
        for key, value in items:
            '<dt>%s</dt>' % key
            '<dd>%s</dd>' % pformat(value)
        '<dt>body</dt>'
        '<dd>'
        # get_request().read_body() would be useful if you wanted
        # to parse the request body as xml, or json, or whatever.
        repr(get_request().read_body())
        '</dd>'
        '</dl>'

    def request:xml(self):
        header('HTTP Request')
        self.request_()
        footer()

def format_sessions:xml():
    session_items = sorted(get_publisher().get_sessions().items())
    if not session_items:
        '<p style="clear:both">No sessions.</p>'
    else:
        '<table style="clear:both">'
        '<caption>Saved Sessions</caption>'
        ('<tr>'
         '<th>session key</th>'
         '<th>owner</th>'
         '<th>effective_user</th>'
         '<th>authentication_time</th>'
         '<th>remote_address</th>'
         '</tr>')
        for id, session in session_items:
            if get_session() is session:
                '<tr class="current">'
            else:
                '<tr>'
            '<td>%s</td>' % id
            '<td>%s</td>' % session.get_owner().get_id()
            '<td>%s</td>' % session.get_effective_user().get_id()
            '<td>%s</td>' % session.get_authentication_time()
            '<td>%s</td>' % session.get_remote_address()
            '</tr>'
        '</table>'
