from rest_framework import serializers

from django.contrib.auth import get_user_model, logout
from django.contrib.auth.password_validation import validate_password
from django.utils.translation import ugettext as _

from misago.conf import settings
from misago.users.online.tracker import clear_tracking
from misago.users.permissions import allow_delete_own_account
from misago.users.validators import validate_email, validate_username


UserModel = get_user_model()

__all__ = [
    'ForumOptionsSerializer',
    'EditSignatureSerializer',
    'ChangeUsernameSerializer',
    'ChangePasswordSerializer',
    'ChangeEmailSerializer',
    'DeleteOwnAccountSerializer',
]


class ForumOptionsSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserModel
        fields = [
            'is_hiding_presence', 'limits_private_thread_invites_to',
            'subscribe_to_started_threads', 'subscribe_to_replied_threads'
        ]
        extra_kwargs = {
            'limits_private_thread_invites_to': {
                'required': True
            },
            'subscribe_to_started_threads': {
                'required': True
            },
            'subscribe_to_replied_threads': {
                'required': True
            },
        }


class EditSignatureSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserModel
        fields = ['signature']

    def validate(self, data):
        if len(data.get('signature', '')) > settings.signature_length_max:
            raise serializers.ValidationError(_("Signature is too long."))

        return data


class ChangeUsernameSerializer(serializers.Serializer):
    username = serializers.CharField(max_length=200, required=False, allow_blank=True)

    def validate(self, data):
        username = data.get('username')

        if not username:
            raise serializers.ValidationError(_("Enter new username."))

        if username == self.context['user'].username:
            raise serializers.ValidationError(_("New username is same as current one."))

        validate_username(username)

        return data

    def change_username(self, changed_by):
        self.context['user'].set_username(self.validated_data['username'], changed_by=changed_by)
        self.context['user'].save(update_fields=['username', 'slug'])


class ChangePasswordSerializer(serializers.Serializer):
    password = serializers.CharField(max_length=200, trim_whitespace=False)
    new_password = serializers.CharField(max_length=200, trim_whitespace=False)

    def validate_password(self, value):
        if not self.context['user'].check_password(value):
            raise serializers.ValidationError(_("Entered password is invalid."))
        return value

    def validate_new_password(self, value):
        validate_password(value, user=self.context['user'])
        return value


class ChangeEmailSerializer(serializers.Serializer):
    password = serializers.CharField(max_length=200, trim_whitespace=False)
    new_email = serializers.CharField(max_length=200)

    def validate_password(self, value):
        if not self.context['user'].check_password(value):
            raise serializers.ValidationError(_("Entered password is invalid."))
        return value

    def validate_new_email(self, value):
        if not value:
            raise serializers.ValidationError(_("You have to enter new e-mail address."))

        if value.lower() == self.context['user'].email.lower():
            raise serializers.ValidationError(_("New e-mail is same as current one."))

        validate_email(value)

        return value


class DeleteOwnAccountSerializer(serializers.Serializer):
    password = serializers.CharField(max_length=200, trim_whitespace=False)

    def validate_password(self, value):
        if not self.context['user'].check_password(value):
            raise serializers.ValidationError(_("Entered password is invalid."))
        return value

    def mark_account_for_deletion(self, request):
        """
        Deleting user account can be costful, so just mark account for deletion, deactivate it
        and sign user out.
        """
        profile = self.context['user']
        allow_delete_own_account(request.user, profile)
        
        logout(request)
        clear_tracking(request)

        profile.mark_for_delete()
