"""Handle dispatcher API requests."""

import copy
import logging
import os
import xmlrpc.client

from django.conf import settings
from rest_framework import generics, status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from dispatch.models import Dispatcher, DispatcherAction
from dispatch.serializers import DispatchMessageSerializer, DispatcherSerializer, DispatcherActionSerializer


log = logging.getLogger('dispatch.views')


class HasSendMessagePermission(IsAuthenticated):
    """Class to check if the authenticated user can send messages via dispatch."""

    def has_permission(self, request, view):
        """Check user permission for dispatch.send_message."""
        if request.user.has_perm('dispatch.send_message'):
            return True

        return False


class DispatcherList(generics.ListAPIView):
    """List all dispatchers."""

    queryset = Dispatcher.objects.all()
    serializer_class = DispatcherSerializer


class DispatcherDetail(generics.RetrieveAPIView):
    """Detail the given dispatcher."""

    queryset = Dispatcher.objects.all()
    serializer_class = DispatcherSerializer


class DispatcherDetailByKey(DispatcherDetail):
    """Detail a specific dispatcher."""

    lookup_field = 'key'


class DispatchMessage(generics.GenericAPIView):
    """Send a message to the given dispatcher."""

    permission_classes = (HasSendMessagePermission,)

    queryset = Dispatcher.objects.all()
    serializer_class = DispatchMessageSerializer

    def get(self, request, *args, **kwargs):
        """Return a default message, since this needs POST."""
        data = {'message': "", 'status': "READY"}
        message = self.serializer_class(data=data)
        return Response(message.initial_data)

    def post(self, request, *args, **kwargs):
        """Accept and dispatch a provided message."""
        dispatcher = self.get_object()
        message = self.serializer_class(data=request.data)
        if message.is_valid():
            for action in dispatcher.actions.all():
                # manipulate the message if desired
                if action.include_key:
                    text = "[{0:s}] {1:s}".format(action.dispatcher.key, message.data['message'])
                else:
                    text = message.data['message']

                if action.type == DispatcherAction.PRIVMSG_TYPE:
                    # connect over XML-RPC and send
                    try:
                        bot_url = 'http://{0:s}:{1:d}/'.format(settings.IRCBOT_XMLRPC_HOST, settings.IRCBOT_XMLRPC_PORT)
                        bot = xmlrpc.client.ServerProxy(bot_url, allow_none=True)
                        log.debug("sending '%s' to channel %s", text, action.destination)
                        bot.reply(None, text, False, action.destination)
                    except Exception as e:
                        new_data = copy.deepcopy(message.data)
                        new_data['status'] = "FAILED - {0:s}".format(str(e))
                        new_message = self.serializer_class(data=new_data)
                        return Response(new_message.initial_data)
                elif action.type == DispatcherAction.FILE_TYPE:
                    # write to file
                    filename = os.path.abspath(action.destination)
                    log.debug("sending '%s' to file %s", text, filename)
                    with open(filename, 'w') as f:
                        f.write(text + '\n')

            new_data = copy.deepcopy(message.data)
            new_data['status'] = "OK"
            new_message = self.serializer_class(data=new_data)
            return Response(new_message.initial_data)

        return Response(message.errors, status=status.HTTP_400_BAD_REQUEST)


class DispatchMessageByKey(DispatchMessage):
    """Dispatch a message for a specific key."""

    lookup_field = 'key'


class DispatcherActionList(generics.ListAPIView):
    """List all dispatchers."""

    queryset = DispatcherAction.objects.all()
    serializer_class = DispatcherActionSerializer


class DispatcherActionDetail(generics.RetrieveAPIView):
    """Detail the given dispatcher."""

    queryset = DispatcherAction.objects.all()
    serializer_class = DispatcherActionSerializer