from bottle import route, redirect, request, jinja2_view, static_file, Jinja2Template, url, abort
from functools import wraps
import math
import collections
import os
import bottle
import json
import functools
from pydbus import SessionBus
from schema import Poll, Choice, Vote, User

MOVED_TEMP = 307
MOVED_PERM = 301

Jinja2Template.defaults = {"url": url, "site_name": "PØLL"}
Jinja2Template.settings = {"autoescape": True}
view = functools.partial(jinja2_view, template_lookup=["templates"])

bus = None
bus_name = "men.meestem.VoteBot"

def guarantee_bus(fn):
    @wraps(fn)
    def func(*args, **kwargs):
        global bus
        if (not bus):
            bus = SessionBus()
        return fn(*args, **kwargs)
    return func

@route('/')
@view("index.html")
def index():
    return {"title": "PØLL - Create new pøll"}    

@route('/create', method="POST")
@guarantee_bus
def create_poll():
    title = request.forms.title
    questions = [(int(k[1:]),v) for k,v in request.forms.decode().items() if (k[0] == 'q') and v]
    questions.sort(key=lambda x: x[0])
    questions = [x[1] for x in questions]
    print(title, questions)

    username = request.forms.user
    uid = int(request.forms.uid)


    controller = bus.get(bus_name, "/men/meestem/VoteBot")
    pid = controller.addPoll(title, questions, username, email, uid & 0xFFFFFFF)

    return redirect("/%d" % (pid), code=301)

@route('/vote', method="POST")
@guarantee_bus
def vote():
    poll_id = int(request.forms.poll_id)
    choice_id = int(request.forms.question)

    username = request.forms.user
    uid = int(request.forms.uid)

    poll = bus.get(bus_name, "/poll/%d" % poll_id)

    poll.voteFor(uid & 0xFFFFFFF, username, choice_id)

    return redirect("/%d/r" % (poll_id))

@route('/favicon.ico')
def favicon():
    return static('favicon.jpg')

@route('/static/:path#.+#', name='static')
def static(path):
    return static_file(path, root="static")

@route('/<poll_id:re:\d+/?>')
@view('poll.html')
@guarantee_bus
def get_poll(poll_id):
    try:
        poll = bus.get(bus_name, '/poll/%s' % (poll_id))
    except KeyError:
        redirect("/", code=MOVED_TEMP)

    title = poll.name
    questions = poll.choices

    return {"poll_id": poll_id, "title": title, "questions": questions}

@route('/<poll_id>/r')
@view('results.html')
@guarantee_bus
def get_poll_results(poll_id):
    try:
        int(poll_id)
    except ValueError:
        redirect("/", code=MOVED_TEMP)
    print("Viewing results for poll #%s" % (poll_id))

    poll = bus.get(bus_name, "/poll/%s" % (poll_id))
    title = poll.name
    pid = poll_id
    total_votes, options = poll.votes
    percentage_dict = {option:round(100*(len(votes)/total_votes)) for option, votes in options.items()}

    return {"pid": pid, "title": title, "options": collections.OrderedDict(sorted(options.items(), key=lambda x: len(x[1]), reverse=True)), "percentages": percentage_dict,
            "total_votes": total_votes}

# read configuration file
config = json.load(open("config.json", "r"))

application = app = bottle.default_app()
app.catchall = False

if __name__ == '__main__':
    app.run(host="0.0.0.0", port="80", debug=True, reloader=True)
