import api
import bson
from api.annotations import (
    api_wrapper,
    log_action,
    require_admin,
    require_login,
    require_teacher
)
from api.common import WebError, WebSuccess
from flask import (
    Blueprint,
    Flask,
    render_template,
    request,
    send_from_directory,
    session
)

blueprint = Blueprint("admin_api", __name__)

@blueprint.route('/problems', methods=['GET'])
@api_wrapper
@require_admin
def get_problem_data_hook():
    has_instances = lambda p : len(p["instances"]) > 0
    problems = list(filter(has_instances, api.problem.get_all_problems(show_disabled=True)))

    for problem in problems:
        problem["reviews"] = api.problem_feedback.get_problem_feedback(pid=problem["pid"])

    data = {
        "problems": problems,
        "bundles": api.problem.get_all_bundles()
    }

    return WebSuccess(data=data)

@blueprint.route('/users', methods=['GET'])
@api_wrapper
@require_admin
def get_all_users_hook():
    users = api.user.get_all_users()
    if users is None:
        return WebError("There was an error query users from the database.")
    return WebSuccess(data=users)

@blueprint.route('/exceptions', methods=['GET'])
@api_wrapper
@require_admin
def get_exceptions_hook():
    try:
        limit = abs(int(request.args.get("limit")))
        exceptions = api.admin.get_api_exceptions(result_limit=limit)
        return WebSuccess(data=exceptions)

    except (ValueError, TypeError):
        return WebError("limit is not a valid integer.")

@blueprint.route('/exceptions/dismiss', methods=['POST'])
@api_wrapper
@require_admin
def dismiss_exceptions_hook():
    trace = request.form.get("trace", None)
    if trace:
        api.admin.dismiss_api_exceptions(trace)
        return WebSuccess(data="Successfuly changed exception visibility.")
    else:
        return WebError(message="You must supply a trace to hide.")

@blueprint.route("/problems/submissions", methods=["GET"])
@api_wrapper
@require_admin
def get_problem():
    submission_data = {p["name"]:api.stats.get_problem_submission_stats(pid=p["pid"]) \
                       for p in api.problem.get_all_problems(show_disabled=True)}
    return WebSuccess(data=submission_data)

@blueprint.route("/problems/availability", methods=["POST"])
@api_wrapper
@require_admin
def change_problem_availability_hook():
    pid = request.form.get("pid", None)
    desired_state = request.form.get("state", None)

    if desired_state == None:
        return WebError("Problems are either enabled or disabled.")
    else:
        state = bson.json_util.loads(desired_state)

    api.admin.set_problem_availability(pid, state)
    return WebSuccess(data="Problem state changed successfully.")


@blueprint.route("/shell_servers", methods=["GET"])
@api_wrapper
@require_admin
def get_shell_servers():
    return WebSuccess(data=api.shell_servers.get_servers())

@blueprint.route("/shell_servers/add", methods=["POST"])
@api_wrapper
@require_admin
def add_shell_server():
    params = api.common.flat_multi(request.form)
    api.shell_servers.add_server(params)
    return WebSuccess("Shell server added.")

@blueprint.route("/shell_servers/update", methods=["POST"])
@api_wrapper
@require_admin
def update_shell_server():
    params = api.common.flat_multi(request.form)

    sid = params.get("sid", None)
    if sid is None:
        return WebError("Must specify sid to be updated")

    api.shell_servers.update_server(sid, params)
    return WebSuccess("Shell server updated.")

@blueprint.route("/shell_servers/remove", methods=["POST"])
@api_wrapper
@require_admin
def remove_shell_server():
    sid = request.form.get("sid", None)
    if sid is None:
        return WebError("Must specify sid to be removed")

    api.shell_servers.remove_server(sid)
    return WebSuccess("Shell server removed.")

@blueprint.route("/shell_servers/load_problems", methods=["POST"])
@api_wrapper
@require_admin
def load_problems_from_shell_server():
    sid = request.form.get("sid", None)

    if sid is None:
        return WebError("Must provide sid to load from.")

    number = api.shell_servers.load_problems_from_server(sid)
    return WebSuccess("Loaded {} problems from the server".format(number))

@blueprint.route("/shell_servers/check_status", methods=["GET"])
@api_wrapper
@require_admin
def check_status_of_shell_server():
    sid = request.args.get("sid", None)

    if sid is None:
        return WebError("Must provide sid to load from.")

    all_online, data = api.shell_servers.get_problem_status_from_server(sid)

    if all_online:
        return WebSuccess("All problems are online", data=data)
    else:
        return WebError("One or more problems are offline. Please connect and fix the errors.", data=data)

@blueprint.route("/bundle/dependencies_active", methods=["POST"])
@api_wrapper
@require_admin
def bundle_dependencies():
    bid = request.form.get("bid", None)
    state = request.form.get("state", None)

    if bid is None:
        return WebError("Must provide bid to load from.")

    if state is None:
        return WebError("Must provide a state to set.")

    state = bson.json_util.loads(state)

    api.problem.set_bundle_dependencies_enabled(bid, state)

    return WebSuccess("Dependencies are now {}.".format("enabled" if state else "disabled"))

@blueprint.route("/settings", methods=["GET"])
@api_wrapper
@require_admin
def get_settings():
    return WebSuccess(data=api.config.get_settings())

@blueprint.route("/settings/change", methods=["POST"])
@api_wrapper
@require_admin
def change_settings():
    data = bson.json_util.loads(request.form["json"])
    api.config.change_settings(data)
    return WebSuccess("Settings updated")

[((322, 354), 'flask.Blueprint', 'Blueprint', (['"""admin_api"""', '__name__'], {}), "('admin_api', __name__)\n", (331, 354), False, 'from flask import Blueprint, Flask, render_template, request, send_from_directory, session\n'), ((840, 861), 'api.common.WebSuccess', 'WebSuccess', ([], {'data': 'data'}), '(data=data)\n', (850, 861), False, 'from api.common import WebError, WebSuccess\n'), ((973, 997), 'api.user.get_all_users', 'api.user.get_all_users', ([], {}), '()\n', (995, 997), False, 'import api\n'), ((1108, 1130), 'api.common.WebSuccess', 'WebSuccess', ([], {'data': 'users'}), '(data=users)\n', (1118, 1130), False, 'from api.common import WebError, WebSuccess\n'), ((1634, 1665), 'flask.request.form.get', 'request.form.get', (['"""trace"""', 'None'], {}), "('trace', None)\n", (1650, 1665), False, 'from flask import Blueprint, Flask, render_template, request, send_from_directory, session\n'), ((2170, 2202), 'api.common.WebSuccess', 'WebSuccess', ([], {'data': 'submission_data'}), '(data=submission_data)\n', (2180, 2202), False, 'from api.common import WebError, WebSuccess\n'), ((2343, 2372), 'flask.request.form.get', 'request.form.get', (['"""pid"""', 'None'], {}), "('pid', None)\n", (2359, 2372), False, 'from flask import Blueprint, Flask, render_template, request, send_from_directory, session\n'), ((2393, 2424), 'flask.request.form.get', 'request.form.get', (['"""state"""', 'None'], {}), "('state', None)\n", (2409, 2424), False, 'from flask import Blueprint, Flask, render_template, request, send_from_directory, session\n'), ((2591, 2637), 'api.admin.set_problem_availability', 'api.admin.set_problem_availability', (['pid', 'state'], {}), '(pid, state)\n', (2625, 2637), False, 'import api\n'), ((2649, 2703), 'api.common.WebSuccess', 'WebSuccess', ([], {'data': '"""Problem state changed successfully."""'}), "(data='Problem state changed successfully.')\n", (2659, 2703), False, 'from api.common import WebError, WebSuccess\n'), ((2994, 3029), 'api.common.flat_multi', 'api.common.flat_multi', (['request.form'], {}), '(request.form)\n', (3015, 3029), False, 'import api\n'), ((3034, 3070), 'api.shell_servers.add_server', 'api.shell_servers.add_server', (['params'], {}), '(params)\n', (3062, 3070), False, 'import api\n'), ((3082, 3115), 'api.common.WebSuccess', 'WebSuccess', (['"""Shell server added."""'], {}), "('Shell server added.')\n", (3092, 3115), False, 'from api.common import WebError, WebSuccess\n'), ((3245, 3280), 'api.common.flat_multi', 'api.common.flat_multi', (['request.form'], {}), '(request.form)\n', (3266, 3280), False, 'import api\n'), ((3399, 3443), 'api.shell_servers.update_server', 'api.shell_servers.update_server', (['sid', 'params'], {}), '(sid, params)\n', (3430, 3443), False, 'import api\n'), ((3455, 3490), 'api.common.WebSuccess', 'WebSuccess', (['"""Shell server updated."""'], {}), "('Shell server updated.')\n", (3465, 3490), False, 'from api.common import WebError, WebSuccess\n'), ((3617, 3646), 'flask.request.form.get', 'request.form.get', (['"""sid"""', 'None'], {}), "('sid', None)\n", (3633, 3646), False, 'from flask import Blueprint, Flask, render_template, request, send_from_directory, session\n'), ((3730, 3766), 'api.shell_servers.remove_server', 'api.shell_servers.remove_server', (['sid'], {}), '(sid)\n', (3761, 3766), False, 'import api\n'), ((3778, 3813), 'api.common.WebSuccess', 'WebSuccess', (['"""Shell server removed."""'], {}), "('Shell server removed.')\n", (3788, 3813), False, 'from api.common import WebError, WebSuccess\n'), ((3959, 3988), 'flask.request.form.get', 'request.form.get', (['"""sid"""', 'None'], {}), "('sid', None)\n", (3975, 3988), False, 'from flask import Blueprint, Flask, render_template, request, send_from_directory, session\n'), ((4082, 4130), 'api.shell_servers.load_problems_from_server', 'api.shell_servers.load_problems_from_server', (['sid'], {}), '(sid)\n', (4125, 4130), False, 'import api\n'), ((4346, 4375), 'flask.request.args.get', 'request.args.get', (['"""sid"""', 'None'], {}), "('sid', None)\n", (4362, 4375), False, 'from flask import Blueprint, Flask, render_template, request, send_from_directory, session\n'), ((4479, 4532), 'api.shell_servers.get_problem_status_from_server', 'api.shell_servers.get_problem_status_from_server', (['sid'], {}), '(sid)\n', (4527, 4532), False, 'import api\n'), ((4866, 4895), 'flask.request.form.get', 'request.form.get', (['"""bid"""', 'None'], {}), "('bid', None)\n", (4882, 4895), False, 'from flask import Blueprint, Flask, render_template, request, send_from_directory, session\n'), ((4908, 4939), 'flask.request.form.get', 'request.form.get', (['"""state"""', 'None'], {}), "('state', None)\n", (4924, 4939), False, 'from flask import Blueprint, Flask, render_template, request, send_from_directory, session\n'), ((5111, 5138), 'bson.json_util.loads', 'bson.json_util.loads', (['state'], {}), '(state)\n', (5131, 5138), False, 'import bson\n'), ((5144, 5199), 'api.problem.set_bundle_dependencies_enabled', 'api.problem.set_bundle_dependencies_enabled', (['bid', 'state'], {}), '(bid, state)\n', (5187, 5199), False, 'import api\n'), ((5562, 5604), 'bson.json_util.loads', 'bson.json_util.loads', (["request.form['json']"], {}), "(request.form['json'])\n", (5582, 5604), False, 'import bson\n'), ((5609, 5641), 'api.config.change_settings', 'api.config.change_settings', (['data'], {}), '(data)\n', (5635, 5641), False, 'import api\n'), ((5653, 5683), 'api.common.WebSuccess', 'WebSuccess', (['"""Settings updated"""'], {}), "('Settings updated')\n", (5663, 5683), False, 'from api.common import WebError, WebSuccess\n'), ((667, 728), 'api.problem_feedback.get_problem_feedback', 'api.problem_feedback.get_problem_feedback', ([], {'pid': "problem['pid']"}), "(pid=problem['pid'])\n", (708, 728), False, 'import api\n'), ((792, 821), 'api.problem.get_all_bundles', 'api.problem.get_all_bundles', ([], {}), '()\n', (819, 821), False, 'import api\n'), ((1035, 1096), 'api.common.WebError', 'WebError', (['"""There was an error query users from the database."""'], {}), "('There was an error query users from the database.')\n", (1043, 1096), False, 'from api.common import WebError, WebSuccess\n'), ((1318, 1366), 'api.admin.get_api_exceptions', 'api.admin.get_api_exceptions', ([], {'result_limit': 'limit'}), '(result_limit=limit)\n', (1346, 1366), False, 'import api\n'), ((1382, 1409), 'api.common.WebSuccess', 'WebSuccess', ([], {'data': 'exceptions'}), '(data=exceptions)\n', (1392, 1409), False, 'from api.common import WebError, WebSuccess\n'), ((1688, 1727), 'api.admin.dismiss_api_exceptions', 'api.admin.dismiss_api_exceptions', (['trace'], {}), '(trace)\n', (1720, 1727), False, 'import api\n'), ((1743, 1803), 'api.common.WebSuccess', 'WebSuccess', ([], {'data': '"""Successfuly changed exception visibility."""'}), "(data='Successfuly changed exception visibility.')\n", (1753, 1803), False, 'from api.common import WebError, WebSuccess\n'), ((1829, 1881), 'api.common.WebError', 'WebError', ([], {'message': '"""You must supply a trace to hide."""'}), "(message='You must supply a trace to hide.')\n", (1837, 1881), False, 'from api.common import WebError, WebSuccess\n'), ((2022, 2074), 'api.stats.get_problem_submission_stats', 'api.stats.get_problem_submission_stats', ([], {'pid': "p['pid']"}), "(pid=p['pid'])\n", (2060, 2074), False, 'import api\n'), ((2471, 2523), 'api.common.WebError', 'WebError', (['"""Problems are either enabled or disabled."""'], {}), "('Problems are either enabled or disabled.')\n", (2479, 2523), False, 'from api.common import WebError, WebSuccess\n'), ((2550, 2585), 'bson.json_util.loads', 'bson.json_util.loads', (['desired_state'], {}), '(desired_state)\n', (2570, 2585), False, 'import bson\n'), ((3351, 3393), 'api.common.WebError', 'WebError', (['"""Must specify sid to be updated"""'], {}), "('Must specify sid to be updated')\n", (3359, 3393), False, 'from api.common import WebError, WebSuccess\n'), ((3682, 3724), 'api.common.WebError', 'WebError', (['"""Must specify sid to be removed"""'], {}), "('Must specify sid to be removed')\n", (3690, 3724), False, 'from api.common import WebError, WebSuccess\n'), ((4025, 4067), 'api.common.WebError', 'WebError', (['"""Must provide sid to load from."""'], {}), "('Must provide sid to load from.')\n", (4033, 4067), False, 'from api.common import WebError, WebSuccess\n'), ((4412, 4454), 'api.common.WebError', 'WebError', (['"""Must provide sid to load from."""'], {}), "('Must provide sid to load from.')\n", (4420, 4454), False, 'from api.common import WebError, WebSuccess\n'), ((4568, 4616), 'api.common.WebSuccess', 'WebSuccess', (['"""All problems are online"""'], {'data': 'data'}), "('All problems are online', data=data)\n", (4578, 4616), False, 'from api.common import WebError, WebSuccess\n'), ((4642, 4738), 'api.common.WebError', 'WebError', (['"""One or more problems are offline. Please connect and fix the errors."""'], {'data': 'data'}), "('One or more problems are offline. Please connect and fix the errors.'\n    , data=data)\n", (4650, 4738), False, 'from api.common import WebError, WebSuccess\n'), ((4976, 5018), 'api.common.WebError', 'WebError', (['"""Must provide bid to load from."""'], {}), "('Must provide bid to load from.')\n", (4984, 5018), False, 'from api.common import WebError, WebSuccess\n'), ((5057, 5097), 'api.common.WebError', 'WebError', (['"""Must provide a state to set."""'], {}), "('Must provide a state to set.')\n", (5065, 5097), False, 'from api.common import WebError, WebSuccess\n'), ((557, 605), 'api.problem.get_all_problems', 'api.problem.get_all_problems', ([], {'show_disabled': '(True)'}), '(show_disabled=True)\n', (585, 605), False, 'import api\n'), ((1462, 1503), 'api.common.WebError', 'WebError', (['"""limit is not a valid integer."""'], {}), "('limit is not a valid integer.')\n", (1470, 1503), False, 'from api.common import WebError, WebSuccess\n'), ((2109, 2157), 'api.problem.get_all_problems', 'api.problem.get_all_problems', ([], {'show_disabled': '(True)'}), '(show_disabled=True)\n', (2137, 2157), False, 'import api\n'), ((2838, 2869), 'api.shell_servers.get_servers', 'api.shell_servers.get_servers', ([], {}), '()\n', (2867, 2869), False, 'import api\n'), ((5417, 5442), 'api.config.get_settings', 'api.config.get_settings', ([], {}), '()\n', (5440, 5442), False, 'import api\n'), ((1269, 1294), 'flask.request.args.get', 'request.args.get', (['"""limit"""'], {}), "('limit')\n", (1285, 1294), False, 'from flask import Blueprint, Flask, render_template, request, send_from_directory, session\n')]