'''Entrypoint for the entire application.'''
from flask import Flask, abort, request, jsonify, Response, send_from_directory
from flask_jwt import JWT, jwt_required, current_identity

from authentication import Authentication
from create_quiz import CreateQuiz
from manage_classes import ManageClasses

auth = Authentication()
manage_classes = ManageClasses()

# FOR DEV PURPOSES
#auth._persist._shelf.clear()
#auth.add_user('jackharrhy', 'foobar123', 'student')
#auth.add_user('barab', 'finite', 'professor')
print('User', auth._persist._shelf['User'])
for user in auth._persist._shelf['User']:
    print(dict(vars(auth._persist._shelf['User'][user])))

print("\n")
print('Class', auth._persist._shelf['Class'])
for _class in auth._persist._shelf['Class']:
    print(dict(vars(auth._persist._shelf['Class'][_class])))

print("\n")
print('Quiz', auth._persist._shelf['Quiz'])
for quiz in auth._persist._shelf['Quiz']:
    print(dict(vars(auth._persist._shelf['Quiz'][quiz])))

print("\n")
print('QuestionBank', auth._persist._shelf['QuestionBank'])
for qbank in auth._persist._shelf['QuestionBank']:
    print(dict(vars(auth._persist._shelf['QuestionBank'][qbank])))
# FOR DEV PURPOSES


def _authenticate(username, password):
    print('auth', username, password)
    auth_result = auth.login(username, password)

    if auth_result['success']:
        print('success', auth_result)
        return auth_result['user']
    else:
        print('fail', auth_result)


def _identity(payload):
    username = payload['identity']
    print('User logging in with username: {}'.format(username))
    return auth.get_user(username)


app = Flask(__name__)
app.debug = True
app.config['SECRET_KEY'] = 'super-secret'
app.config['JWT_AUTH_URL_RULE'] = '/api/login'

jwt = JWT(app, _authenticate, _identity)

@app.after_request
def apply_caching(response):
    response.headers.add('Access-Control-Allow-Origin', '*')
    response.headers.add('Access-Control-Allow-Headers', '*')
    response.headers.add('Access-Control-Allow-Credentials', 'true')
    response.headers.add('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS,POST,PUT')
    return response

@app.route('/')
@app.route('/home')
@app.route('/login')
@app.route('/account')
def send_static_homepage():
    return send_from_directory('static', 'index.html')

@app.route('/<path:path>')
def send_static(path):
    return send_from_directory('static', path)

@app.route('/static/<path:path>')
def send_static_static(path):
    return send_from_directory('static/static', path)

@app.route('/static/js/<path:path>')
def send_static_static_js(path):
    return send_from_directory('static/static/js', path)

def user_as_json_without_password(username):
    return jsonify(auth.return_flat_user(username))

@app.route('/api/whoami')
@jwt_required()
def whoami():
    return user_as_json_without_password(current_identity.username)

@app.route('/api/user', methods=['POST'])
@jwt_required()
def _new_user():
    if not current_identity.is_role('professor'):
        return Response(status=403)

    data = request.get_json()
    auth_result = auth.add_user(
        data['username'],
        data['password'],
        data['role']
    )

    if auth_result['success']:
        return Response(status=204)
    else:
        return Response(auth_result['message'], status=400)

@app.route('/api/user/<username>', methods=['GET', 'POST'])
@jwt_required()
def _user(username):
    if not current_identity.is_role('professor'):
        return Response(status=403)

    if request.method == 'GET':
        user = auth.get_user(username)

        if user:
            return user_as_json_without_password(username)
        else:
            return Response(status=404)

    elif request.method == 'POST':
        user = auth.get_user(username)
        data = request.get_json()

        if data['new_class']:
            class_creation_result = manage_classes.assign_class_to_user(username, data['new_class'])

            if class_creation_result['success']:
                return Response(status=204)
            else:
                return Response(class_creation_result['message'], status=400)

        return Response(status=400)

@app.route('/api/class/', methods=['POST'])
@jwt_required()
def _create_class():
    if not current_identity.is_role('professor'):
        return Response(status=403)

    data = request.get_json()

    class_creation_result = manage_classes.add_class(
        data['classname'],
        current_identity.id,
    )

    if class_creation_result['success']:
        return Response(class_creation_result['class_id'], status=200)
    else:
        return Response(class_creation_result['message'], status=400)

@app.route('/api/changepassword', methods=['POST'])
@jwt_required()
def _change_password():
    data = request.get_json()
    auth_result = auth.change_password(
        current_identity.username,
        data['oldpassword'],
        data['newpassword'],
    )

    if auth_result['success']:
        return Response(status=204)
    else:
        return Response(auth_result['message'], status=400)

@app.route('/api/quiz', methods=['POST'])
@jwt_required()
def _create_quiz():
    if not current_identity.is_role('professor'):
        abort(403)

    data = request.get_json()

    new_quiz = CreateQuiz(
        data['quizname'],
        data['numattempts']
    )
    new_quiz.add_start_time(
        data['syear'],
        data['smonth'],
        data['sday'],
        data['shour'],
        data['smin']
    )
    new_quiz.add_end_time(
        data['eyear'],
        data['emonth'],
        data['eday'],
        data['ehour'],
        data['emin']
    )
    new_quiz.add_time_limit(data['timelimit'])

    questions = data['questions']
    for question in questions:
        new_quiz.add_question(
            question['questiontext'],
            question['points'],
            question['answerdict'],
            question['choicesdict']
        )

    new_quiz.add_all_questions_to_bank()
    new_quiz.pass_to_storage()

    return new_quiz.get_id()
