# Copyright (c) 2012-2016 Seafile Ltd.
# encoding: utf-8
import os
import logging
import json

from django.core.cache import cache
from django.http import HttpResponse, HttpResponseRedirect, Http404, \
    HttpResponseBadRequest
from django.utils.translation import ugettext as _, activate
from django.contrib import messages
from django.utils.html import escape

import seaserv
from seaserv import seafile_api
from pysearpc import SearpcError

from seahub.share.forms import FileLinkShareForm, \
    UploadLinkShareForm
from seahub.share.models import FileShare, UploadLinkShare
from seahub.share.signals import share_repo_to_user_successful
from seahub.auth.decorators import login_required, login_required_ajax
from seahub.base.decorators import require_POST
from seahub.contacts.signals import mail_sended
from seahub.views import is_registered_user, check_folder_permission
from seahub.utils import string2list, IS_EMAIL_CONFIGURED, check_filename_with_rename, \
    is_valid_username, is_valid_email, send_html_email, is_org_context, \
    gen_token, normalize_cache_key, get_site_name
from seahub.utils.mail import send_html_email_with_dj_template
from seahub.settings import SITE_ROOT, REPLACE_FROM_EMAIL, \
        ADD_REPLY_TO_HEADER, SHARE_LINK_EMAIL_LANGUAGE, \
        SHARE_LINK_AUDIT_CODE_TIMEOUT
from seahub.profile.models import Profile

# Get an instance of a logger
logger = logging.getLogger(__name__)


# rpc wrapper
def is_org_repo_owner(username, repo_id):
    owner = seaserv.seafserv_threaded_rpc.get_org_repo_owner(repo_id)
    return True if owner == username else False


def org_share_repo(org_id, repo_id, from_user, to_user, permission):
    return seaserv.seafserv_threaded_rpc.org_add_share(org_id, repo_id,
                                                       from_user, to_user,
                                                       permission)


def org_remove_share(org_id, repo_id, from_user, to_user):
    return seaserv.seafserv_threaded_rpc.org_remove_share(org_id, repo_id,
                                                          from_user, to_user)


# functions
def share_to_group(request, repo, group, permission):
    """Share repo to group with given permission.
    """
    repo_id = repo.id
    group_id = group.id
    from_user = request.user.username

    if is_org_context(request):
        org_id = request.user.org.org_id
        group_repo_ids = seafile_api.get_org_group_repoids(org_id, group.id)
    else:
        group_repo_ids = seafile_api.get_group_repoids(group.id)

    if repo.id in group_repo_ids:
        return False

    try:
        if is_org_context(request):
            org_id = request.user.org.org_id
            seafile_api.add_org_group_repo(repo_id, org_id, group_id,
                                           from_user, permission)
        else:
            seafile_api.set_group_repo(repo_id, group_id, from_user,
                                       permission)
        return True
    except Exception as e:
        logger.error(e)
        return False


def share_to_user(request, repo, to_user, permission):
    """Share repo to a user with given permission.
    """
    repo_id = repo.id
    from_user = request.user.username

    if from_user == to_user:
        return False

    # permission check
    org_id = None
    if is_org_context(request):
        org_id = request.user.org.org_id
        if not seaserv.ccnet_threaded_rpc.org_user_exists(org_id, to_user):
            return False
    else:
        if not is_registered_user(to_user):
            return False

    try:
        if is_org_context(request):
            org_id = request.user.org.org_id
            org_share_repo(org_id, repo_id, from_user, to_user, permission)
        else:
            seafile_api.share_repo(repo_id, from_user, to_user, permission)
    except SearpcError as e:
        logger.error(e)
        return False
    else:
        # send a signal when sharing repo successful
        share_repo_to_user_successful.send(sender=None,
                                           from_user=from_user,
                                           to_user=to_user, repo=repo,
                                           path='/', org_id=org_id)
        return True


# share link
@login_required_ajax
def send_shared_link(request):
    """
    Handle ajax post request to send file shared link.
    """
    if not request.method == 'POST':
        raise Http404

    content_type = 'application/json; charset=utf-8'

    if not IS_EMAIL_CONFIGURED:
        data = json.dumps({'error': _('Failed to send email, email service is not properly configured, please contact administrator.')})
        return HttpResponse(data, status=500, content_type=content_type)

    form = FileLinkShareForm(request.POST)
    if form.is_valid():
        email = form.cleaned_data['email']
        file_shared_link = form.cleaned_data['file_shared_link']
        file_shared_name = form.cleaned_data['file_shared_name']
        file_shared_type = form.cleaned_data['file_shared_type']
        extra_msg = escape(form.cleaned_data['extra_msg'])

        to_email_list = string2list(email)
        send_success, send_failed = [], []
        # use contact_email, if present
        username = Profile.objects.get_contact_email_by_user(request.user.username)
        for to_email in to_email_list:
            if not is_valid_email(to_email):
                send_failed.append(to_email)
                continue

            if SHARE_LINK_EMAIL_LANGUAGE:
                activate(SHARE_LINK_EMAIL_LANGUAGE)

            # Add email to contacts.
            mail_sended.send(sender=None, user=request.user.username,
                             email=to_email)

            c = {
                'email': request.user.username,
                'to_email': to_email,
                'file_shared_link': file_shared_link,
                'file_shared_name': file_shared_name,
            }

            if extra_msg:
                c['extra_msg'] = extra_msg

            if REPLACE_FROM_EMAIL:
                from_email = username
            else:
                from_email = None  # use default from email

            if ADD_REPLY_TO_HEADER:
                reply_to = username
            else:
                reply_to = None

            try:
                if file_shared_type == 'f':
                    c['file_shared_type'] = _("file")
                    send_html_email(_('A file is shared to you on %s') % get_site_name(),
                                    'shared_link_email.html',
                                    c, from_email, [to_email],
                                    reply_to=reply_to
                                    )
                else:
                    c['file_shared_type'] = _("directory")
                    send_html_email(_('A directory is shared to you on %s') % get_site_name(),
                                    'shared_link_email.html',
                                    c, from_email, [to_email],
                                    reply_to=reply_to)

                send_success.append(to_email)
            except Exception:
                send_failed.append(to_email)

        if len(send_success) > 0:
            data = json.dumps({"send_success": send_success, "send_failed": send_failed})
            return HttpResponse(data, status=200, content_type=content_type)
        else:
            data = json.dumps({"error": _("Internal server error, or please check the email(s) you entered")})
            return HttpResponse(data, status=400, content_type=content_type)
    else:
        return HttpResponseBadRequest(json.dumps(form.errors),
                                      content_type=content_type)


@login_required
def save_shared_link(request):
    """Save public share link to one's library.
    """
    username = request.user.username
    token = request.GET.get('t', '')
    dst_repo_id = request.POST.get('dst_repo', '')
    dst_path = request.POST.get('dst_path', '')

    next_page = request.META.get('HTTP_REFERER', None)
    if not next_page:
        next_page = SITE_ROOT

    if not dst_repo_id or not dst_path:
        messages.error(request, _('Please choose a directory.'))
        return HttpResponseRedirect(next_page)

    if check_folder_permission(request, dst_repo_id, dst_path) != 'rw':
        messages.error(request, _('Permission denied'))
        return HttpResponseRedirect(next_page)

    try:
        fs = FileShare.objects.get(token=token)
    except FileShare.DoesNotExist:
        raise Http404

    src_repo_id = fs.repo_id
    src_path = os.path.dirname(fs.path)
    obj_name = os.path.basename(fs.path)

    new_obj_name = check_filename_with_rename(dst_repo_id, dst_path, obj_name)

    seafile_api.copy_file(src_repo_id, src_path, obj_name,