#!/usr/bin/env python
# coding: utf-8
#
# Copyright 2010 Alexandre Fiori
# based on the original Tornado by Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import cyclone.escape
import cyclone.redis
import cyclone.sqlite
import cyclone.util
import cyclone.web
import cyclone.websocket
import cyclone.xmlrpc
from cyclone.bottle import run, route

from twisted.internet import defer

class BaseHandler(cyclone.web.RequestHandler):
    @property
    def redisdb(self):
        return self.settings.db_handlers.redis

    def get_current_user(self):
        print "Getting user cookie"
        return self.get_secure_cookie("user")


@route("/")
def index(cli):
    cli.write('<a href="/auth/login">sign in</a>')


@route("/auth/login")
def auth_login_page(cli):
    cli.write("""
    <html><body><form method="post">
    username: <input type="text" name="usr"/><br/>
    password: <input type="password" name="pwd"/><br/>
    <input type="submit">
    </form></body></html>
    """)


@route("/auth/login", method="post")
@defer.inlineCallbacks
def auth_login(cli):
    usr = cli.get_argument("usr")
    pwd = cli.get_argument("pwd")

    try:
        redis_pwd = yield cli.redisdb.get("cyclone:%s" % usr)
    except Exception, e:
        log.msg("Redis failed to get('cyclone:%s'): %s" % (usr, str(e)))
        raise cyclone.web.HTTPError(503) # Service Unavailable

    if pwd != str(redis_pwd):
        cli.write("Invalid user or password.<br>"
                  '<a href="/auth/login">try again</a>')
    else:
        cli.set_secure_cookie("user", usr)
        cli.redirect(cli.get_argument("next", "/private"))


@route("/auth/logout")
@cyclone.web.authenticated
def auth_logout(cli):
    cli.clear_cookie("user")
    cli.redirect("/")


@route("/private")
@cyclone.web.authenticated
def private(cli):
    cli.write("Hi, %s<br/>" % cli.current_user)
    cli.write("""<a href="/auth/logout">logout</a>""")


class WebSocketHandler(cyclone.websocket.WebSocketHandler):
    def connectionMade(self, *args, **kwargs):
        print "connection made:", args, kwargs

    def messageReceived(self, message):
        self.sendMessage("echo: %s" % message)

    def connectionLost(self, why):
        print "connection lost:", why


class XmlrpcHandler(cyclone.xmlrpc.XmlrpcRequestHandler):
    allowNone = True
    def xmlrpc_echo(self, text):
        return text


try:
    raise COMMENT_THIS_LINE_AND_LOG_TO_DAILY_FILE
    from twisted.python.logfile import DailyLogFile
    logFile = DailyLogFile.fromFullPath("server.log")
    print("Logging to daily log file: server.log")
except Exception, e:
    import sys
    logFile = sys.stdout

run(host="127.0.0.1", port=8888,
    log=logFile,
    debug=True,
    static_path="./static",
    template_path="./template",
    locale_path="./locale",
    login_url="/auth/login",
    cookie_secret="32oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=",
    base_handler=BaseHandler,
    db_handlers=cyclone.util.ObjectDict(
        #sqlite=cyclone.sqlite.InlineSQLite(":memory:"),
        redis=cyclone.redis.lazyRedisConnectionPool(),
    ),
    more_handlers=[
        (r"/websocket", WebSocketHandler),
        (r"/xmlrpc",    XmlrpcHandler),
    ])

