from Blueprints.BaseRequestParser import base_parser, handle_request
from Rest.ProjectsREST import ProjectsREST
from flask_restx import Namespace, Resource, inputs
from Rest.Answer import message_response_model
from Blueprints.APIModels import a_project, a_own_project, a_invite, a_join_request, post_a_project, a_user

api = Namespace('Projects', path='/projects', description='Project related Operations')

get_project_parser = base_parser.copy()
get_project_parser.add_argument('project_id', location='args', required=True)

join_request_parser = base_parser.copy()
join_request_parser.add_argument('denied', location='args', required=True, type=inputs.boolean)

invite_parser = base_parser.copy()
invite_parser.add_argument('invitee_id', location='args', required=True, type=str)

ignore_invite_parser = base_parser.copy()
ignore_invite_parser.add_argument('invite_id', location='args', required=True, type=str)
ignore_invite_parser.add_argument('ignore', location='args', required=False, type=inputs.boolean)

get_invites_parser = base_parser.copy()
get_invites_parser.add_argument('filter', location='args', required=False, type=str)

ban_parser = base_parser.copy()
ban_parser.add_argument('user_to_ban_id', location='args', required=True, type=str)

unban_parser = base_parser.copy()
unban_parser.add_argument('user_to_unban_id', location='args', required=True, type=str)

create_proj_parser = base_parser.copy()
create_proj_parser.add_argument('name', location='args', required=True, type=str)
create_proj_parser.add_argument('is_private', location='args', required=False, type=inputs.boolean)
create_proj_parser.add_argument('is_visible', location='args', required=False, type=inputs.boolean)
create_proj_parser.add_argument('has_exam', location='args', required=False, type=inputs.boolean)

a_projects_response = message_response_model(a_project)
a_own_project_response = message_response_model(a_own_project)
a_single_project_response = message_response_model(a_project, single=True)
a_join_request_response = message_response_model(a_join_request)
a_invite_response = message_response_model(a_invite)

a_user_response = message_response_model(a_user)

default_project_mask = """
message,
result{
    id,default_project_mask
    name,
    description,
    has_exam,
    is_private,
    is_visible,
    channel_id,
    project_type,
    show_only_reviewed_media,
    project_leader{
        id,
        username,
        display_name,
        profile_pic_id
    },
    banned_user{
        id,
        username,
        display_name,
        profile_pic_id
    },
    number_of_users,
    member{
        id,
        username,
        display_name,
        profile_pic_id
    },
    invites{
        id,
        user_username,
        user_id,
        user_display_name,
        user_profile_pic_id
    },
    join_requests{
        *
    },
    media{
        *
    }
}"""

default_own_project_mask = """
message,
result{
    id,
    name,
    description,
    has_exam,
    is_private,
    is_visible,
    channel_id,
    project_type,
    show_only_reviewed_media,
    project_leader{
        id,
        username,
        display_name,
        profile_pic_id
    },
    banned_user{
        id,
        username,
        display_name,
        profile_pic_id
    },
    last_post{
        id,
        content,
        date_created,
        author_id,
        author_display_name,
        author_username,
        author_profile_pic_id,
        rank,
        linked_user,
        anonymous,
        image_id
    },
    last_post_read_id,
    number_of_users,
    member{
        id,
        username,
        display_name,
        profile_pic_id
    },
    invites{
        id,
        user_username,
        user_id,
        user_display_name,
        user_profile_pic_id
    },
    join_requests{
        *
    },
    media{
        *
    }
}"""


@api.route('/')
class Project(Resource):
    @api.doc(parser=get_project_parser)
    def get(self):
        return handle_request(parser=get_project_parser,
                              arg_dict={'project_id': None},
                              rest_function=ProjectsREST.get_project,
                              model=a_single_project_response,
                              mask=default_project_mask)

    @api.doc(parser=base_parser, body=post_a_project)
    def post(self):
        return handle_request(json_data=True,
                              rest_function=ProjectsREST.post_project,
                              model=a_single_project_response,
                              mask=default_project_mask)

    @api.doc(parser=get_project_parser)
    def delete(self):
        return handle_request(parser=get_project_parser,
                              arg_dict={'project_id': None},
                              rest_function=ProjectsREST.delete_projects, )


@api.route('/my')
class MyProjects(Resource):
    @api.doc(parser=base_parser)
    def get(self):
        return handle_request(rest_function=ProjectsREST.get_projects_my,
                              model=a_own_project_response,
                              mask=default_own_project_mask)


@api.route('/all')
class AllProjects(Resource):
    @api.doc(parser=base_parser)
    def get(self):
        return handle_request(rest_function=ProjectsREST.get_projects_all,
                              model=a_projects_response,
                              mask=default_project_mask)


@api.route('/users/<project_id>')
@api.doc(params={'project_id': 'Id of a project'})
class GetProjectUsers(Resource):
    @api.doc(parser=base_parser)
    def get(self, project_id):
        return handle_request(path_args=[project_id],
                              rest_function=ProjectsREST.get_project_users,
                              model=a_user_response)


@api.route('/join/<project_id>')
@api.doc(params={'project_id': 'Id of a project'})
class JoinProject(Resource):
    @api.doc(parser=base_parser)
    def post(self, project_id):
        return handle_request(path_args=[project_id],
                              rest_function=ProjectsREST.post_projects_join)


@api.route('/leave/<project_id>')
@api.doc(params={'project_id': 'Id of a project'})
class LeaveProject(Resource):
    @api.doc(parser=base_parser)
    def post(self, project_id):
        return handle_request(path_args=[project_id],
                              rest_function=ProjectsREST.post_projects_leave)


@api.route('/join_request/<request_id>')
@api.doc(params={'request_id': 'Id of a join-request for a project'})
class JoinRequest(Resource):
    @api.doc(parser=join_request_parser)
    def post(self, request_id):
        return handle_request(parser=join_request_parser,
                              path_args=[request_id],
                              arg_dict={'denied': False},
                              rest_function=ProjectsREST.post_projects_join_request)


@api.route('/join_requests/<project_id>')
@api.doc(params={'project_id': 'Id of a project'})
class JoinRequests(Resource):
    @api.doc(parser=base_parser)
    def get(self, project_id):
        return handle_request(path_args=[project_id],
                              rest_function=ProjectsREST.get_projects_join_request,
                              model=a_join_request_response)


@api.route('/invites')
class Invites(Resource):
    @api.doc(parser=get_invites_parser)
    def get(self):
        return handle_request(parser=get_invites_parser,
                              arg_dict={'filter': 'all'},
                              rest_function=ProjectsREST.get_user_invites,
                              model=a_invite_response)


@api.route('/invite/<project_id>')
@api.doc(params={'project_id': 'Id of a project'})
class Invite(Resource):
    @api.doc(parser=invite_parser)
    def post(self, project_id):
        return handle_request(parser=invite_parser,
                              path_args=[project_id],
                              arg_dict={'invitee_id': None},
                              rest_function=ProjectsREST.post_projects_invite)

    @api.doc(parser=base_parser)
    def get(self, project_id):
        return handle_request(path_args=[project_id],
                              rest_function=ProjectsREST.get_projects_invites,
                              model=a_invite_response)


@api.route('/ignore')
class Ignore(Resource):
    @api.doc(parser=ignore_invite_parser)
    def post(self):
        return handle_request(parser=ignore_invite_parser,
                              arg_dict={'invite_id': None, 'ignore': True},
                              rest_function=ProjectsREST.post_ignore_project_invite)


@api.route('/ban/<project_id>')
@api.doc(params={'project_id': 'Id of a project'})
class Ban(Resource):
    @api.doc(parser=ban_parser)
    def post(self, project_id):
        return handle_request(parser=ban_parser,
                              path_args=[project_id],
                              arg_dict={'user_to_ban_id': None},
                              rest_function=ProjectsREST.post_ban_user)


@api.route('/unban/<project_id>')
@api.doc(params={'project_id': 'Id of a project'})
class UnBan(Resource):
    @api.doc(parser=unban_parser)
    def post(self, project_id):
        return handle_request(parser=unban_parser,
                              path_args=[project_id],
                              arg_dict={'user_to_unban_id': None},
                              rest_function=ProjectsREST.post_unban_user)
