from flask import Flask, redirect, flash, render_template, session, g, request, get_flashed_messages
from wtforms import Form, BooleanField, StringField, PasswordField, validators, SubmitField, IntegerField, DateTimeField
from wtforms.validators import ValidationError
from flask_wtf import FlaskForm
from flask_bootstrap import Bootstrap
import time
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import exc, update
import hashlib
import bcrypt
import os
import werkzeug.exceptions
import wtforms
from wtforms.fields import EmailField
from wtforms.widgets import NumberInput

import hra.config as config
import hra.web.html as html
import hra.db as db

import json


import logging
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.ERROR)

static_dir = os.path.abspath('static')
app = Flask(__name__, static_folder=static_dir)

app.config.from_object(config)
Bootstrap(app)

db.flask_db = SQLAlchemy(app, metadata=db.metadata)


class NeedLoginError(werkzeug.exceptions.Forbidden):
    description = 'Need to log in'


class MenuItem:
    url: str
    name: str

    def __init__(self, url: str, name: str):
        self.url = url
        self.name = name


def init_request():
    path = request.path
    # XXX: Když celá aplikace běží v adresáři, request.path je relativní ke kořeni aplikace, ne celého webu
    if path.startswith('/static/') or path.startswith('/assets/'):
        # Pro statické soubory v development nasazení nepotřebujeme nastavovat
        # nic dalšího (v ostrém nasazení je servíruje uwsgi)
        return

    user = None
    g.user = None
    g.org = False
    token = request.args.get('token')
    if token is not None:
        user = db.get_session().query(db.User).filter_by(token=token).first()
        if user is None:
            raise werkzeug.exceptions.Forbidden("Wrong token.")
    if 'uid' in session:
        user = db.get_session().query(db.User).filter_by(id=session['uid']).first()
    path = request.path
    if path.startswith('/org/'):
        if not user or not user.org:
            raise werkzeug.exceptions.Forbidden()
    g.user = user
    g.org = g.user and g.user.org

    g.menu = [
            MenuItem('/', "Domů"),
        ]
    if g.org:
        g.menu += [
            MenuItem(app.url_for(pages.web_org_games.__name__), "Hry"),
            MenuItem(app.url_for(pages.web_org_users.__name__), "Uživatelé"),
            MenuItem(app.url_for(pages.web_org_logs.__name__)+"#main_table" , "Logy"),
        ]
    else:
        g.menu += [
        ]



app.before_request(init_request)


@app.errorhandler(werkzeug.exceptions.HTTPException)
def handle_exception(e):
    path = request.path
    if path.startswith('/api/'):
        ses = db.get_session()
        ses.rollback()
        response = e.get_response()
        response.data = json.dumps({
            "status": "error",
            "description": e.description,
            "http-code": e.code,
            "http-name": e.name,
        })
        response.content_type = "application/json"
        x = db.Log(
                source_ip=request.remote_addr,
                user_id=g.user.id if g.user is not None else None,
                endpoint=db.Endpoint.error,
                status="http-error",
                text=f"{e.code} ({e.name}): {e.description}",
                url=request.path,
                get=request.args,
                time=datetime.now(),
        )
        ses.add(x)
        ses.commit()
        return response
    else:
        return e

import hra.web.pages as pages
import hra.web.api