from django_future.csrf import ensure_csrf_cookie
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
from django.contrib.auth.models import User
from django.core.context_processors import csrf
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseForbidden, Http404
from django.shortcuts import redirect
import json
import logging
import re

from courseware.courses import get_course_with_access
from mitxmako.shortcuts import render_to_response, render_to_string

from .models import CourseUserGroup
from . import cohorts

import track.views


log = logging.getLogger(__name__)


def json_http_response(data):
    """
    Return an HttpResponse with the data json-serialized and the right content
    type header.
    """
    return HttpResponse(json.dumps(data), content_type="application/json")


def split_by_comma_and_whitespace(s):
    """
    Split a string both by commas and whitespice.  Returns a list.
    """
    return re.split(r'[\s,]+', s)


@ensure_csrf_cookie
def list_cohorts(request, course_id):
    """
    Return json dump of dict:

    {'success': True,
     'cohorts': [{'name': name, 'id': id}, ...]}
    """
    get_course_with_access(request.user, course_id, 'staff')

    all_cohorts = [{'name': c.name, 'id': c.id}
               for c in cohorts.get_course_cohorts(course_id)]

    return json_http_response({'success': True,
                            'cohorts': all_cohorts})


@ensure_csrf_cookie
@require_POST
def add_cohort(request, course_id):
    """
    Return json of dict:
    {'success': True,
     'cohort': {'id': id,
                'name': name}}

                or

    {'success': False,
     'msg': error_msg} if there's an error
    """
    get_course_with_access(request.user, course_id, 'staff')

    name = request.POST.get("name")
    if not name:
        return json_http_response({'success': False,
                                'msg': "No name specified"})

    try:
        cohort = cohorts.add_cohort(course_id, name)
    except ValueError as err:
        return json_http_response({'success': False,
                                'msg': str(err)})

    return json_http_response({'success': 'True',
                            'cohort': {
                                'id': cohort.id,
                                'name': cohort.name
                                }})


@ensure_csrf_cookie
def users_in_cohort(request, course_id, cohort_id):
    """
    Return users in the cohort.  Show up to 100 per page, and page
    using the 'page' GET attribute in the call.  Format:

    Returns:
        Json dump of dictionary in the following format:
        {'success': True,
         'page': page,
         'num_pages': paginator.num_pages,
         'users': [{'username': ..., 'email': ..., 'name': ...}]
    }
    """
    get_course_with_access(request.user, course_id, 'staff')

    # this will error if called with a non-int cohort_id.  That's ok--it
    # shoudn't happen for valid clients.
    cohort = cohorts.get_cohort_by_id(course_id, int(cohort_id))

    paginator = Paginator(cohort.users.all(), 100)
    page = request.GET.get('page')
    try:
        users = paginator.page(page)
    except PageNotAnInteger:
        # return the first page
        page = 1
        users = paginator.page(page)
    except EmptyPage:
        # Page is out of range.  Return last page
        page = paginator.num_pages
        contacts = paginator.page(page)

    user_info = [{'username': u.username,
                  'email': u.email,
                  'name': '{0} {1}'.format(u.first_name, u.last_name)}
                  for u in users]

    return json_http_response({'success': True,
                            'page': page,
                            'num_pages': paginator.num_pages,
                            'users': user_info})


@ensure_csrf_cookie
@require_POST
def add_users_to_cohort(request, course_id, cohort_id):
    """
    Return json dict of:

    {'success': True,
     'added': [{'username': username,
                'name': name,
                'email': email}, ...],
     'conflict': [{'username_or_email': ...,
                    'msg': ...}],  # in another cohort
     'present': [str1, str2, ...],    # already there
     'unknown': [str1, str2, ...]}
    """
    get_course_with_access(request.user, course_id, 'staff')

    cohort = cohorts.get_cohort_by_id(course_id, cohort_id)

    users = request.POST.get('users', '')
    added = []
    present = []
    conflict = []
    unknown = []
    for username_or_email in split_by_comma_and_whitespace(users):
        try:
            user = cohorts.add_user_to_cohort(cohort, username_or_email)
            added.append({'username': user.username,
                          'name': "{0} {1}".format(user.first_name, user.last_name),
                          'email': user.email,
                          })
        except ValueError:
            present.append(username_or_email)
        except User.DoesNotExist:
            unknown.append(username_or_email)
        except cohorts.CohortConflict as err:
            conflict.append({'username_or_email': username_or_email,
                              'msg': str(err)})


    return json_http_response({'success': True,
                            'added': added,
                            'present': present,
                            'conflict': conflict,
                            'unknown': unknown})


@ensure_csrf_cookie
@require_POST
def remove_user_from_cohort(request, course_id, cohort_id):
    """
    Expects 'username': username in POST data.

    Return json dict of:

    {'success': True} or
    {'success': False,
     'msg': error_msg}
    """
    get_course_with_access(request.user, course_id, 'staff')

    username = request.POST.get('username')
    if username is None:
        return json_http_response({'success': False,
                                'msg': 'No username specified'})

    cohort = cohorts.get_cohort_by_id(course_id, cohort_id)
    try:
        user = User.objects.get(username=username)
        cohort.users.remove(user)
        return json_http_response({'success': True})
    except User.DoesNotExist:
        log.debug('no user')
        return json_http_response({'success': False,
                                'msg': "No user '{0}'".format(username)})


def debug_cohort_mgmt(request, course_id):
    """
    Debugging view for dev.
    """
    # add staff check to make sure it's safe if it's accidentally deployed.
    get_course_with_access(request.user, course_id, 'staff')

    context = {'cohorts_ajax_url': reverse('cohorts',
                                           kwargs={'course_id': course_id})}
    return render_to_response('/course_groups/debug.html', context)
