from http import HTTPStatus
from flask import Flask, Response, config, json, jsonify, request, request_started
from uuid import uuid4
import sqlite3
import numbers
from flask import g

DATABASE = './forum.db'

def get_db():
    db = getattr(g, '__database', None)
    if db is None:
        db = g.__database = sqlite3.connect(DATABASE)
    return db

app = Flask(__name__)

@app.teardown_appcontext
def close_connection(_):
    db = getattr(g, '__database', None)
    if db is not None:
        db.close()


print("Connected to SQLite database")

@app.route('/api/message')
def get_messages():
    cur = get_db().cursor()
    res = cur.execute("SELECT message_id, position, message FROM message")
    messages = jsonify(list(map(lambda m: {'message_id': m[0], 'position': json.loads(m[1]), 'message': m[2]}, res.fetchall())))
    return messages

@app.route('/api/new_message', methods=['POST'])
def new_message():
    db = get_db()
    cur = db.cursor()
    position = list(json.loads(request.form['position']))
    if len(position) != 3:
        return Response(status=HTTPStatus.BAD_REQUEST)
    for elem in position:
        if not isinstance(elem, numbers.Number):
            return Response(status=HTTPStatus.BAD_REQUEST)
    position = json.dumps(position)
    message = str(request.form['message'])
    token = request.form['token']
    res = cur.execute(f"SELECT user_id FROM user WHERE token='{token}'")
    res = res.fetchone()
    if res is not None:
        (user_id,) = res
        id = str(uuid4())
        cur.execute("INSERT INTO message VALUES(?, ?, ?, ?)", (id, user_id, position, message));
        db.commit()
        return Response(status=HTTPStatus.NO_CONTENT)
    else:
        return Response(status=HTTPStatus.BAD_REQUEST)

@app.route('/api/gen_token')
def gen_token():
    db = get_db()
    cur = db.cursor()
    id = str(uuid4())
    token = str(uuid4())
    cur.execute("INSERT INTO user VALUES(?, ?)", (id, token));
    db.commit()
    return { 'token': token }

@app.route('/api/remove_message', methods=['DELETE'])
def remove_message():
    db = get_db()
    cur = db.cursor()
    token = request.form['token']
    message_id = request.form['message_id']
    res = cur.execute(f"SELECT user_id FROM user WHERE token='{token}'")
    res = res.fetchone()
    if res is not None:
        (user_id,) = res
        res = cur.execute(f"SELECT message_id, user_id FROM message WHERE message_id='{message_id}'")
        res = res.fetchone()
        if res is not None:
            (message_id, message_user_id) = res
            if message_user_id == user_id:
                cur.execute(f"DELETE FROM message WHERE message_id='{message_id}'")
                db.commit()
                return Response(status=HTTPStatus.NO_CONTENT)
            else:
                return Response(status=HTTPStatus.UNAUTHORIZED)
        else:
            return Response(status=HTTPStatus.BAD_REQUEST)
    else:
        return Response(status=HTTPStatus.BAD_REQUEST)

@app.route('/api/edit_message', methods=['PUT'])
def edit_message():
    db = get_db()
    cur = db.cursor()
    token = request.form['token']
    message_id = request.form['message_id']
    new_message = request.form['message']
    res = cur.execute(f"SELECT user_id FROM user WHERE token='{token}'")
    res = res.fetchone()
    if res is not None and new_message is not None:
        (user_id,) = res
        res = cur.execute(f"SELECT message_id, user_id FROM message WHERE message_id='{message_id}'")
        res = res.fetchone()
        if res is not None:
            (message_id, message_user_id) = res
            if message_user_id == user_id:
                cur.execute(f"UPDATE message SET message = '{new_message}' WHERE message_id='{message_id}'");
                db.commit()
                return Response(status=HTTPStatus.NO_CONTENT)
            else:
                return Response(status=HTTPStatus.UNAUTHORIZED)
        else:
            return Response(status=HTTPStatus.BAD_REQUEST)
    else:
        return Response(status=HTTPStatus.BAD_REQUEST)