import logging
import sys

from django.contrib.auth.models import User, Group
from django.core.exceptions import PermissionDenied

from xmodule.modulestore import Location

'''
This code is somewhat duplicative of access.py in the LMS. We will unify the code as a separate story
but this implementation should be data compatible with the LMS implementation
'''

# define a couple of simple roles, we just need ADMIN and EDITOR now for our purposes
INSTRUCTOR_ROLE_NAME = 'instructor'
STAFF_ROLE_NAME = 'staff'

# we're just making a Django group for each location/role combo
# to do this we're just creating a Group name which is a formatted string
# of those two variables


def get_course_groupname_for_role(location, role):
    loc = Location(location)
    # hack: check for existence of a group name in the legacy LMS format <role>_<course>
    # if it exists, then use that one, otherwise use a <role>_<course_id> which contains
    # more information
    groupname = '{0}_{1}'.format(role, loc.course)

    if len(Group.objects.filter(name=groupname)) == 0:
        groupname = '{0}_{1}'.format(role, loc.course_id)

    return groupname


def get_users_in_course_group_by_role(location, role):
    groupname = get_course_groupname_for_role(location, role)
    (group, created) = Group.objects.get_or_create(name=groupname)
    return group.user_set.all()


'''
Create all permission groups for a new course and subscribe the caller into those roles
'''


def create_all_course_groups(creator, location):
    create_new_course_group(creator, location, INSTRUCTOR_ROLE_NAME)
    create_new_course_group(creator, location, STAFF_ROLE_NAME)


def create_new_course_group(creator, location, role):
    groupname = get_course_groupname_for_role(location, role)
    (group, created) = Group.objects.get_or_create(name=groupname)
    if created:
        group.save()

    creator.groups.add(group)
    creator.save()

    return

'''
This is to be called only by either a command line code path or through a app which has already
asserted permissions
'''


def _delete_course_group(location):
    # remove all memberships
    instructors = Group.objects.get(name=get_course_groupname_for_role(location, INSTRUCTOR_ROLE_NAME))
    for user in instructors.user_set.all():
        user.groups.remove(instructors)
        user.save()

    staff = Group.objects.get(name=get_course_groupname_for_role(location, STAFF_ROLE_NAME))
    for user in staff.user_set.all():
        user.groups.remove(staff)
        user.save()

'''
This is to be called only by either a command line code path or through an app which has already
asserted permissions to do this action
'''


def _copy_course_group(source, dest):
    instructors = Group.objects.get(name=get_course_groupname_for_role(source, INSTRUCTOR_ROLE_NAME))
    new_instructors_group = Group.objects.get(name=get_course_groupname_for_role(dest, INSTRUCTOR_ROLE_NAME))
    for user in instructors.user_set.all():
        user.groups.add(new_instructors_group)
        user.save()

    staff = Group.objects.get(name=get_course_groupname_for_role(source, STAFF_ROLE_NAME))
    new_staff_group = Group.objects.get(name=get_course_groupname_for_role(dest, STAFF_ROLE_NAME))
    for user in staff.user_set.all():
        user.groups.add(new_staff_group)
        user.save()


def add_user_to_course_group(caller, user, location, role):
    # only admins can add/remove other users
    if not is_user_in_course_group_role(caller, location, INSTRUCTOR_ROLE_NAME):
        raise PermissionDenied

    if user.is_active and user.is_authenticated:
        groupname = get_course_groupname_for_role(location, role)

        group = Group.objects.get(name=groupname)
        user.groups.add(group)
        user.save()
        return True

    return False


def get_user_by_email(email):
    user = None
    # try to look up user, return None if not found
    try:
        user = User.objects.get(email=email)
    except:
        pass

    return user


def remove_user_from_course_group(caller, user, location, role):
    # only admins can add/remove other users
    if not is_user_in_course_group_role(caller, location, INSTRUCTOR_ROLE_NAME):
        raise PermissionDenied

    # see if the user is actually in that role, if not then we don't have to do anything
    if is_user_in_course_group_role(user, location, role) == True:
        groupname = get_course_groupname_for_role(location, role)

        group = Group.objects.get(name=groupname)
        user.groups.remove(group)
        user.save()


def is_user_in_course_group_role(user, location, role):
    if user.is_active and user.is_authenticated:
        # all "is_staff" flagged accounts belong to all groups
        return user.is_staff or user.groups.filter(name=get_course_groupname_for_role(location, role)).count() > 0

    return False
