def get_user_stats():
    """Gets user stats

    Returns the following data points:
        total number of users
        total number of verified users
        total number of users registered within N number of days
        total number of users that logged within N number of days
        total number of submission
        total number of submissions created within N number of days
        average age of users

    no request body

    :rtype: json
    """
    num_users = User.objects.count()
    num_verified = User.objects().count()

    num_submission = Submission.objects.count()
    # avg_age = User.objects
    pass
def create_user():
    """Create user

    Create and register a new user

    :param body: Creates a new user object
    :type body: dict | bytes

    :rtype: None
    """
    if request.content_type != 'application/json':
        return Response('Failed: Content-type must be application/json', 415)

    r = request.get_json()
    # kind of a lot of if statements but I feel like this is more consistent
    # and gives more useful debugging information that just default invalid request
    if 'username' not in r:
        return Response('Failed: Please provide a username', 400)
    username = ''.join(filter(str.isalpha, r['username']))
    if 'dob' not in r:
        return Response('Failed: Please provide a dob', 400)
    if User.objects(username=username):
        return Response('Failed: username already exists', 409)
    newUser = User(username=username, dob=r['dob'])
    if 'firstname' not in r:
        return Response('Failed: Please provide a firstname', 400)
    newUser.firstname = r['firstname']
    if 'lastname' not in r:
        return Response('Failed: please provide a lastname', 400)
    newUser.lastname = r['lastname']
    try:
        newUser.save()
    except Exception as e:
        print(str(datetime.now()) + ' ', e)
        return Response('Failed: invalid request', 400)
    return Response('Success: user added', 200)
def get_submissions():
    """Get a list of all submissions filtered based on certian criteria.

    Returns an array of all submissions. It can be filtered based on quizId and/or moduleId and/or userId.
    For example, a user can request all of their sumissions for any combination of moduleId or quizId.
    Must have at least one filter otherwise error

    :query param submission: The Id of the submission that a user is requesting.
    :type submission_id: str
    :query param quiz: The quiz Id that a user wants all submissions for
    :type quiz: str
    :query param module: The module Id that a user wants all submissions for
    :type module: str
    :query param user: The username of the user that the admin wants all the submissions for
    :type user: str

    :rtype: JSON
    """

    # If we are given a submission Id no filtering needs to be done. Return the document referenced by the id.
    submissionId = request.args.get('submission', None)
    username = request.args.get('user', None)
    quizId = request.args.get('quiz', None)
    moduleId = request.args.get('module', None)

    if submissionId:
        err = Submission.error_checker(submissionId)
        if err:
            return err
        # submission cannot be combined with other queries
        elif username or quizId or moduleId:
            return Response(
                'Failed: Submission query cannot be combined with other queries',
                400)
        # submission id is corrent and no other queries have been specified
        else:
            return Response(Submission.objects.get(id=submissionId).to_json(),
                            mimetype='application/json')

    # if submissionId is not specified do further filtering
    subs = Submission.objects()
    if not username and not quizId and not moduleId:
        return Response(
            'Failed: specify at least one filter to view submissions', 412)

    if username:
        if User.objects(username=username):
            user = User.objects.get(username=username)
            subs = subs.filter(user_id=user.id)

    if moduleId:
        err = Module.error_checker(moduleId)
        if err:
            return Response(err)
        subs = subs.filter(module_id=moduleId)

    if quizId:
        err = Module.error_checker(quizId)
        if err:
            return Response(err)
        subs = Submission.objects(quiz_id=quizId)

    if subs:
        return Response(subs.order_by('-grade').to_json(),
                        200,
                        mimetype='application/json')
    return Response('No content', 204)
def submit_quiz():
    """Submit a quiz for a user

    request body

    :rtype: none
    """
    if request.content_type != 'application/json':
        return Response('Failed: Content-type must be application/json', 415)
    r = request.get_json()

    # check if the oids are valid and exist
    err = User.error_checker(r['user_id'])
    if err:
        return err
    err = Quiz.error_checker(id=r['quiz_id'])
    if err:
        return err
    err = Module.error_checker(id=r['module_id'])
    if err:
        return err

    # check if the quiz is part of the module
    if not Module.objects(id=r['module_id'], quiz=r['quiz_id']):
        return Response('Failed: quiz is not a member of module', 400)

    # if the module has a parent check to see if the user has completed it
    module = Module.objects.get(id=r['module_id'])
    if module.parent:
        if not User.objects(id=r['user_id'], completed_modules__module_id=module.parent):
            return Response('Failed: user has not completed the parent module', 403)

    # build submission object
    sub = Submission(user_id=r['user_id'],
                     quiz_id=r['quiz_id'], module_id=r['module_id'])

    # grade quiz
    sub = grade_and_verify(r['user_answers'], sub)

    # check for any errors in grading the quiz
    if isinstance(sub, Response):
        return sub

    # No errors so save the submission
    sub.save()

    # update the completed modules field
    if sub.grade >= 80:
        completed = True

        # check if the user has completed all the quizzes for the module
        for e in module.quiz:
            if not Submission.objects(user_id=r['user_id'], module_id=module.id, quiz_id=e.id, grade__gte=80):
                completed = False

        # If so and the module is not already marked as complete, mark it as complete
        if completed and not User.objects(id=r['user_id'], completed_modules__module_id=module.id):
            User.objects(id=r['user_id']).update(push__completed_modules=Completed_Modules(
                module_id=module.id, module_name=module.module_name))

    return Response(sub.to_json(), 200, mimetype='application/json')
def add_all():
    # adds words
    try:
        word_test = Dictionary(word='test',
                               url='http://test.com',
                               in_dictionary=False,
                               times_requested=7)
        word_hello = Dictionary(word='hello',
                                url='http://hello.com',
                                in_dictionary=True,
                                times_requested=2)
        word_sick = Dictionary(word='sick',
                               url='http://sick.com',
                               in_dictionary=False,
                               times_requested=1)
        word_foo = Dictionary(word='foo',
                              url='http://foo.com',
                              in_dictionary=True,
                              times_requested=10)
        word_bar = Dictionary(word='bar',
                              url='http://bar.com',
                              in_dictionary=True,
                              times_requested=30)
        word_food = Dictionary(word='food',
                               url='http://food.com',
                               in_dictionary=False,
                               times_requested=5)
        word_goodbye = Dictionary(word='goodbye',
                                  url='http://goodbye.com',
                                  in_dictionary=True,
                                  times_requested=1)
        word_pizza = Dictionary(word='pizza',
                                url='http://pizza.com',
                                in_dictionary=True,
                                times_requested=7)
        word_hack = Dictionary(word='hack',
                               url='http://hack.com',
                               in_dictionary=False,
                               times_requested=30)
        word_computer = Dictionary(word='computer',
                                   url='http://computer.com',
                                   in_dictionary=False,
                                   times_requested=10)

        # import json
        # print(word_test.to_json())
        word_test.save()
        word_hello.save()
        word_sick.save()
        word_foo.save()
        word_bar.save()
        word_food.save()
        word_goodbye.save()
        word_pizza.save()
        word_hack.save()
        word_computer.save()

        q0 = Question(question_text='Sign for test', word=word_test)
        q1 = Question(question_text='Sign for hello', word=word_hello)
        q2 = Question(question_text='Sign for sick', word=word_sick)
        q3 = Question(question_text='Sign for foo', word=word_foo)
        q4 = Question(question_text='Sign for bar', word=word_bar)
        q5 = Question(question_text='Sign for food', word=word_food)
        q6 = Question(question_text='Sign for goodbye', word=word_goodbye)
        q7 = Question(question_text='Sign for pizza', word=word_pizza)
        q8 = Question(question_text='Sign for hack', word=word_hack)
        q9 = Question(question_text='Sign for computer', word=word_computer)

        q0.save()
        q1.save()
        q2.save()
        q3.save()
        q4.save()
        q5.save()
        q6.save()
        q7.save()
        q8.save()
        q9.save()

        quiz_1 = Quiz(quiz_name='Test quiz 1',
                      details='This is the first test quiz',
                      questions=[q0, q1, q2, q3, q4])
        quiz_1.save()

        quiz_2 = Quiz(quiz_name='Test quiz 2',
                      details='This is the second test quiz',
                      questions=[q5, q8, q9])
        quiz_2.save()

        quiz_3 = Quiz(quiz_name='Test quiz 3',
                      details='This is the third test quiz',
                      questions=[q3, q5, q6, q7])
        quiz_3.save()

        quiz_4 = Quiz(quiz_name='Test quiz 4',
                      details='This is the forth test quiz',
                      questions=[q6, q8])
        quiz_4.save()

        mod_1 = Module(module_name='Test module 1',
                       details='This is the first module',
                       words=[
                           word_computer, word_test, word_hello, word_sick,
                           word_foo, word_bar, word_hack, word_food
                       ],
                       quiz=[quiz_1, quiz_2])

        mod_2 = Module(
            module_name='Test module 2',
            details='This is the two module',
            words=[word_foo, word_food, word_goodbye, word_pizza, word_hack],
            quiz=[quiz_3])

        mod_3 = Module(module_name='Test module 3',
                       details='This is the three module',
                       words=[word_goodbye, word_hack],
                       quiz=[quiz_4])

        mod_1.save()
        mod_2.save()
        mod_3.save()

        mod_3.parent = mod_2.id
        mod_3.save()

        mod_2.parent = mod_1.id
        mod_2.save()

        mod_1.save()

        user_1 = User(username='******',
                      firstname='jon',
                      lastname='wick',
                      dob='1964-09-02')
        user_1.creation_date = '2019-09-13 15:47:18.171396'
        comp1 = Completed_Modules(module_id=mod_1.id,
                                  module_name=mod_1.module_name)

        user_1.completed_modules = [comp1]
        user_1.save()

        ans0 = UserAnswers(question_id=q0.id,
                           user_answer=q0.word.word,
                           correct_answer=q0.word.word)
        ans1 = UserAnswers(question_id=q1.id,
                           user_answer=q1.word.word,
                           correct_answer=q1.word.word)
        ans2 = UserAnswers(question_id=q2.id,
                           user_answer=word_bar.word,
                           correct_answer=q2.word.word)
        ans3 = UserAnswers(question_id=q3.id,
                           user_answer=q3.word.word,
                           correct_answer=q3.word.word)
        ans4 = UserAnswers(question_id=q4.id,
                           user_answer=q4.word.word,
                           correct_answer=q4.word.word)
        sub_1 = Submission(user_id=user_1,
                           quiz_id=quiz_1,
                           module_id=mod_1,
                           user_answers=[ans0, ans1, ans2, ans3, ans4],
                           grade=4)
        sub_1.save()

        ans5 = UserAnswers(question_id=q3.id,
                           user_answer=q3.word.word,
                           correct_answer=q3.word.word)
        ans6 = UserAnswers(question_id=q5.id,
                           user_answer=q5.word.word,
                           correct_answer=q5.word.word)
        ans7 = UserAnswers(question_id=q6.id,
                           user_answer=q6.word.word,
                           correct_answer=q6.word.word)
        ans8 = UserAnswers(question_id=q7.id,
                           user_answer=q7.word.word,
                           correct_answer=q7.word.word)

        sub_2 = Submission(user_id=user_1,
                           quiz_id=quiz_3,
                           module_id=mod_2,
                           user_answers=[ans5, ans6, ans7, ans8],
                           grade=4)
        sub_2.save()

        ans9 = UserAnswers(question_id=q6.id,
                           user_answer=word_foo.word,
                           correct_answer=q6.word.word)
        ans10 = UserAnswers(question_id=q8.id,
                            user_answer=word_bar.word,
                            correct_answer=q8.word.word)

        sub_3 = Submission(user_id=user_1,
                           quiz_id=quiz_4,
                           module_id=mod_2,
                           user_answers=[ans9, ans10],
                           grade=0)
        sub_3.save()

    except Exception:
        print("An error occured filling the database.")
        print("================== ERROR =====================")
        traceback.print_exc()
        print("==============================================")
        print("Cleaning up ...")
        myclient.drop_database("asl_tutor")
        print("Done")