# -*- encoding: utf-8 -*-
import hashlib
import json
import os
import re

import magic
from perpetualfailure.db import session
from pyramid.authentication import (
    Authenticated,
    Everyone,
)
from pyramid.httpexceptions import (
    HTTPException,
    HTTPBadRequest,
    HTTPFound,
    HTTPNotFound,
    HTTPForbidden,
)
from pyramid.view import view_config
from sqlalchemy.sql.expression import func

import temporals_web.gmod.models as m


@view_config(
    route_name='servers.gmod.loading',
    renderer="gmod/loading.mako",
)
def gmod_loading(request):
    id_magic_number = 76561197960265728

    community_id = int(request.GET["steamid"])
    auth_server = (community_id - id_magic_number) & 1
    auth_id = (community_id - id_magic_number - auth_server) / 2
    steam_id = "STEAM_0:%i:%i" % (auth_server, auth_id)

    player = request.steamweb.player_profile(request.GET["steamid"])

    data = {}
    for mode in session.query(m.LS_Gamemode).all():
        data[mode.name] = mode
    game_data = json.dumps(data, cls=m.ObjectEncoder)

    return {"steamid": steam_id, "player": player, "game_data": game_data}


@view_config(route_name='servers.gmod.background')
def gmod_background(request):
    map = None
    if "map" in request.GET:
        map = request.GET["map"]

    gamemode = None
    if "gamemode" in request.GET:
        gamemode = request.GET["gamemode"]

    query = session.query(m.LS_Background)
    query = query.filter(m.LS_Background.gamemode.in_([gamemode, None]))
    query = query.filter(m.LS_Background.map == map)

    if query.count() < 1:
        query = session.query(m.LS_Background)
        query = query.filter(m.LS_Background.map == map)

        if query.count() < 1:
            query = session.query(m.LS_Background)
            query = query.filter(m.LS_Background.map == map, m.LS_Background.gamemode == None)

            if query.count() < 1:
                query = session.query(m.LS_Background)
                query = query.filter(m.LS_Background.gamemode == gamemode)

                if query.count() < 1:
                    query = session.query(m.LS_Background)

    bg = query.order_by(func.random()).first()

    return HTTPFound(location=request.resolve(bg.url))


@view_config(
    route_name='servers.gmod.acp.loading',
    renderer="gmod/acp/loading.mako",
    permission=Authenticated,
)
def acp_loading(request):
    modes = session.query(m.LS_Gamemode)
    return {"gamemodes": modes}


@view_config(
    route_name='servers.gmod.acp.background.gallery',
    renderer="gmod/acp/background/gallery.mako",
    permission=Authenticated,
)
def acp_background_gallery(request):
    backgrounds = session.query(m.LS_Background).all()
    return {"backgrounds": backgrounds}


@view_config(
    route_name='servers.gmod.acp.background.add',
    renderer="gmod/acp/background/edit.mako",
    permission=Authenticated,
)
def acp_background_add(request):
    background = m.LS_Background()
    if not request.permits("create", background):
        return HTTPForbidden()

    r = background_update(request, background, upload=True)
    if isinstance(r, HTTPException):
        return r
    return {"background": background, "upload": True}


@view_config(
    route_name='servers.gmod.acp.background.edit',
    renderer="gmod/acp/background/edit.mako",
    permission=Authenticated,
)
def acp_background_edit(request):
    background = session.query(m.LS_Background).filter(m.LS_Background.id==request.matchdict["id"]).first()
    if not request.permits("edit", background):
        return HTTPForbidden()

    r = background_update(request, background)
    if isinstance(r, HTTPException):
        return r
    return {"background": background, "upload": False}


@view_config(
    route_name='servers.gmod.acp.gamemode.add',
    renderer="gmod/acp/gamemode.mako",
    permission=Authenticated,
)
def acp_gamemode_add(request):
    mode = m.LS_Gamemode()
    if not request.permits("create", mode):
        return HTTPForbidden()

    r = gamemode_update(request, mode)
    if isinstance(r, HTTPException):
        return r

    return {"gamemode": mode}


@view_config(
    route_name='servers.gmod.acp.gamemode.edit',
    renderer="gmod/acp/gamemode.mako",
    permission=Authenticated,
)
def acp_gamemode_edit(request):
    mode = session.query(m.LS_Gamemode).filter(m.LS_Gamemode.id==request.matchdict["id"]).first()
    if not request.permits("edit", mode):
        return HTTPForbidden()

    r = gamemode_update(request, mode)
    if isinstance(r, HTTPException):
        return r

    return {"gamemode": mode}


def gamemode_update(request, gamemode):
    if request.method != "POST":
        return None

    for key in ['title', 'name', 'rules', 'extrainfo']:
        if key not in request.POST:
            return HTTPBadRequest()

    def clean(text):
        lines = text.split("\n")
        output = []
        for line in lines:
            if oldline == line and line.strip():
                if not output:
                    output.append("")
                output[-1] = (output[-1] + " " + line.strip()).strip()
            elif line.strip():
                output.append(line.strip())
        return output

    gamemode.title = request.params['title']
    gamemode.name = request.params['name']
    gamemode.rules = clean(request.params['rules'])
    gamemode.extrainfo = clean(request.params['extrainfo'])
    session.add(gamemode)
    session.flush()
    return HTTPFound(location=request.route_path('servers.gmod.acp.gamemode.edit', id=gamemode.id))


def background_update(request, gamemode, upload=False):
    if request.method != "POST":
        return None

    for key in ['map', 'gamemode']:
        if key not in request.POST:
            return HTTPBadRequest()

    if upload:
        if 'image' not in request.POST or not request.POST['image'].file:
            return HTTPBadRequest()

        image = request.POST['image'].file
        mime = magic.from_buffer(image.read(1024), mime=True)
        if not mime.startswith("image/"):
            return HTTPBadRequest()
        ext = mime.split("/")[-1]
        if ext not in ["png", "jpeg", "jpg", "gif", "bmp", "tiff", "targa"]:
            return HTTPBadRequest()

        image.seek(0)
        hash = hashlib.sha1(image.read()).hexdigest()
        image.seek(0)
        cdn_path = os.path.join("bg", "%s.%s" % (hash, ext))
        path = os.path.join(request.registry.settings["upload_path"], cdn_path)

        with open(path, "w") as targetFile:
            targetFile.write(image.read())
        gamemode.url = "cdn:%s" % cdn_path

    gamemode.map = request.params['map']
    gamemode.gamemode = request.params['gamemode'] if request.params['gamemode'] else None
    session.add(gamemode)
    session.flush()
    return HTTPFound(location=request.route_path('servers.gmod.acp.background.edit', id=gamemode.id))
            oldline = line
            if line.startswith("- "):
                line = line[2:]
            line = re.sub("^[0-9]+\. ", "", line)