from flask import Flask
from flask import request
from flask import render_template
from flask_cors import cross_origin
from manim_utils import ManimHelper
from code_generator import CodeGenerator
from video_generator import generate_video
import json
import sqlite3
import os

app = Flask(__name__)
DATABASE = 'database/om.db'


@app.before_first_request
def create_db():
    if not os.path.exists(DATABASE):
        connection = sqlite3.connect(DATABASE)
        cursor = connection.cursor()
        with app.open_resource('schema.sql') as f:
            cursor.executescript(f.read().decode('utf8'))
        connection.commit()


def get_db():
    db = sqlite3.connect(DATABASE)
    db.row_factory = sqlite3.Row
    return db


def db_operate(command):
    db = get_db()
    cur = db.execute(command)
    db.commit()
    result = cur.fetchall()
    db.close()
    return result


@app.route('/')
@cross_origin()
def root():
    return render_template('index.html')


@app.route('/register')
@cross_origin()
def register():
    username = request.args.get('username')
    password = request.args.get('password')
    sql_user_str = 'SELECT username FROM user WHERE username=\'{0}\''.format(username)
    result = db_operate(sql_user_str)
    if len(result) == 0:
        sql_str = 'INSERT INTO user (username, password) VALUES (\'{0}\', \'{1}\')'.format(username, password)
        db_operate(sql_str)
        return json.dumps({'status': 'successful'})
    else:
        return json.dumps({'status': 'fail'})


@app.route('/login')
@cross_origin()
def login():
    username = request.args.get('username')
    password = request.args.get('password')
    sql_str = 'SELECT password FROM user WHERE username=\'{0}\''.format(username)
    result = db_operate(sql_str)
    if len(result) != 0:
        if password == result[0][0]:
            sql_dir_str = 'SELECT name FROM directory WHERE owner=\'{0}\''.format(username)
            result_dir = db_operate(sql_dir_str)
            name_list = []
            for name in result_dir:
                name_list.append(name[0])
            print(result_dir)
            return json.dumps({'status': 'successful', 'dir': name_list})
        else:
            return json.dumps({'status': 'fail'})
    else:
        return json.dumps({'status': 'fail'})


@app.route('/class')
@cross_origin()
def get_class():
    manim_helper = ManimHelper()
    class_list = manim_helper.get_class_list()
    return json.dumps(class_list)


@app.route('/param')
@cross_origin()
def get_param():
    function = request.args.get('function')
    manim_helper = ManimHelper()
    arguments = manim_helper.get_arguments(function)
    return json.dumps(arguments)


@app.route('/function')
@cross_origin()
def get_function():
    class_name = request.args.get('class')
    manim_helper = ManimHelper()
    functions = manim_helper.get_function(str(class_name))
    return json.dumps(functions)


@app.route('/generate', methods=['POST'])
@cross_origin()
def generate():
    codes = json.loads(request.get_data())
    username = codes['username']
    scene_name = codes['scene_name']
    quality = codes['quality']
    sql_str = 'SELECT id FROM directory WHERE owner=\'{0}\' AND name=\'{1}\''.format(username, scene_name)
    result = db_operate(sql_str)
    if len(result) == 0:
        sql_create_str = 'INSERT INTO directory (owner, name) VALUES (\'{0}\', \'{1}\')'.format(username, scene_name)
        db_operate(sql_create_str)
        result = db_operate(sql_str)
    directory_name = result[0][0]
    code_generator = CodeGenerator()
    if codes['mode'] == 'interactive':
        code_generator.assemble_code(codes)
    # Put to user directory
    directory_path = 'static/{0}/'.format(directory_name)
    code_file_path = 'static/{0}/{0}.py'.format(directory_name)
    video_file_path = 'static/{0}/'.format(directory_name)
    asset_file_path = 'static/{0}/'.format(directory_name)
    video_name = scene_name
    if codes['mode'] == 'interactive':
        code_generator.to_file(directory_path, code_file_path)
    elif codes['mode'] == 'python':
        code_generator.py_to_file(codes['codes'], directory_path, code_file_path)
    w, h = generate_video(code_file_path, asset_file_path, video_file_path, video_name, quality)
    return json.dumps({'status': 'successful'})


@app.route('/video')
@cross_origin()
def show_video():
    username = request.args.get('username')
    scene_name = request.args.get('scene_name')
    quality = request.args.get('quality')
    sql_str = 'SELECT id FROM directory WHERE owner=\'{0}\' AND name=\'{1}\''.format(username, scene_name)
    result = db_operate(sql_str)
    if len(result) == 0:
        return json.dumps({'status': 'fail'})
    directory_name = result[0][0]
    video_file_path = 'static/{0}/'.format(directory_name)
    video_name = scene_name
    w = 2560
    h = 1440
    if quality == 'w':
        w = 2560
        h = 1440
    elif quality == 'h':
        w = 1920
        h = 1080
    elif quality == 'm':
        w = 1280
        h = 720
    elif quality == 'l':
        w = 854
        h = 480
    return render_template('video_presentator.html', width=w, height=h, video=video_file_path + video_name + '.mp4')


if __name__ == '__main__':
    app.run()
