from __future__ import absolute_import

import six

from django import forms
from rest_framework import serializers
from rest_framework.response import Response

from sentry.exceptions import PluginError
from sentry.plugins import plugins
from sentry.api.bases.project import ProjectEndpoint
from sentry.api.exceptions import ResourceDoesNotExist
from sentry.api.serializers import serialize
from sentry.api.serializers.models.plugin import PluginWithConfigSerializer

ERR_ALWAYS_ENABLED = 'This plugin is always enabled.'
ERR_FIELD_REQUIRED = 'This field is required.'

OK_UPDATED = 'Successfully updated configuration.'


class ProjectPluginDetailsEndpoint(ProjectEndpoint):
    def _get_plugin(self, plugin_id):
        try:
            return plugins.get(plugin_id)
        except KeyError:
            raise ResourceDoesNotExist

    def get(self, request, project, plugin_id):
        plugin = self._get_plugin(plugin_id)

        context = serialize(
            plugin, request.user, PluginWithConfigSerializer(project))

        return Response(context)

    def post(self, request, project, plugin_id):
        """
        Enable plugin
        """
        plugin = self._get_plugin(plugin_id)

        if not plugin.can_disable:
            return Response({'detail': ERR_ALWAYS_ENABLED}, status=400)

        plugin.enable(project)

        return Response(status=201)

    def delete(self, request, project, plugin_id):
        """
        Disable plugin
        """
        plugin = self._get_plugin(plugin_id)

        if not plugin.can_disable:
            return Response({'detail': ERR_ALWAYS_ENABLED}, status=400)

        plugin.disable(project)

        return Response(status=204)

    def put(self, request, project, plugin_id):
        plugin = self._get_plugin(plugin_id)

        config = plugin.get_config(
            project=project,
        )

        cleaned = {}
        errors = {}
        for field in config:
            key = field['name']
            value = request.DATA.get(key)

            if field.get('required') and not value:
                errors[key] = ERR_FIELD_REQUIRED

            try:
                value = plugin.validate_config_field(
                    project=project,
                    name=key,
                    value=value,
                    actor=request.user,
                )
            except (forms.ValidationError, serializers.ValidationError, PluginError) as e:
                errors[key] = e.message

            if not errors.get(key):
                cleaned[key] = value

        try:
            cleaned = plugin.validate_config(
                project=project,
                config=cleaned,
                actor=request.user,
            )
        except PluginError as e:
            errors['__all__'] = e.message

        if errors:
            return Response({
                'errors': errors,
            }, status=400)

        for key, value in six.iteritems(cleaned):
            plugin.set_option(
                project=project,
                key=key,
                value=value,
            )

        return Response({'message': OK_UPDATED})

@@ -2956,24 +2956,54 @@
 s(cleaned):%0A
+            if not value:%0A    
             
@@ -3009,16 +3009,18 @@
  plugin.
+un
 set_opti
@@ -3023,16 +3023,20 @@
 option(%0A
+    
         
@@ -3076,16 +3076,20 @@
         
+    
 key=key,
@@ -3085,24 +3085,165 @@
    key=key,%0A
+                )%0A            else:%0A                plugin.set_option(%0A                    project=project,%0A                    key=key,%0A    
             
@@ -3251,32 +3251,36 @@
    value=value,%0A
+    
             )%0A%0A 

Handle optional values in plugin API (#4081)