from AccessControl import getSecurityManager
from plone import api
from plone.app.dexterity.interfaces import IDXFileFactory
from plone.base.permissions import AddPortalContent
from plone.uuid.interfaces import IUUID
from ploneintranet import api as pi_api
from ploneintranet.core import _
from ploneintranet.workspace.utils import in_workspace
from Products.CMFCore.utils import getToolByName
from Products.Five.browser import BrowserView
from Products.PluggableAuthService.interfaces.plugins import IAuthenticationPlugin

import json
import mimetypes


class VerifyPasswordResetAllowed(BrowserView):
    """
    Check if users are allowed to reset their password.
    Redirect to given URL otherwise.
    This mimics the way the old rejectAnonymous script from
    Archetypes used to work.
    """

    def is_allowed(self, profile=None):
        """A user is allowed if:
        - site settings allow it
        - it has a source field that is not an authentication plugin id
        """
        enable_password_reset = api.portal.get_registry_record(
            "ploneintranet.userprofile.enable_password_reset", default=False
        )
        if not enable_password_reset:
            return False
        external_source_id = api.portal.get_registry_record(
            "ploneintranet.userprofile.primary_external_user_source"
        )
        if not external_source_id:
            return True
        if profile is None:
            profile = pi_api.userprofile.get_current()
        if not profile:
            return True
        if profile.source != external_source_id:
            return True
        pas = api.portal.get_tool("acl_users")
        return external_source_id not in pas.plugins.listPluginIds(
            IAuthenticationPlugin
        )

    def redirect_with_message(self, redirect_url=""):
        message = _("Resetting your own password is not supported.")
        api.portal.show_message(message, self.request, "error")
        if not redirect_url:
            redirect_url = self.context.absolute_url()
        self.request.response.redirect(redirect_url)

    def __call__(self, redirect_url=""):
        if self.is_allowed():
            return True
        self.redirect_with_message(redirect_url=redirect_url)


class ImagePickerJson(BrowserView):
    """
    Returns Images in current Folder in a redactor json format
    [
        {
            "id": 1,
            "title": "Air Canada Landmark Agreement",
            "url": "/media/air-canada-landmark-agreement.jpg",
            "thumb": "/media/air-canada-landmark-agreement.jpg"
        },
        {
            "id": 2,
            "title": "A380",
            "url": "/media/air-france-a380.jpg",
            "thumb": "/media/air-france-a380.jpg",
        }
    ]
    """

    def __call__(self):
        catalog = api.portal.get_tool("portal_catalog")
        results = catalog(
            portal_type="Image",
            path={"query": "/".join(self.context.getPhysicalPath())},
        )
        images = [
            {
                "id": img["getId"],
                "title": img["Title"],
                "url": "%s/@@images/image/3col" % img.getURL(),
                "thumb": "%s/@@images/image/preview" % img.getURL(),
            }
            for img in results
        ]
        return json.dumps(images)


class ImageUploadJson(BrowserView):
    def __call__(self):
        """Upload view for redactor editor.
        Based on plone.app.content.browser.file
        """
        # Check if user has permission to add content here
        sm = getSecurityManager()
        if not sm.checkPermission(AddPortalContent, self.context):
            response = self.request.RESPONSE
            response.setStatus(403)
            return "You are not authorized to add content to this folder."

        req = self.request
        if req.REQUEST_METHOD != "POST":
            return

        files = []
        if "file" in self.request.form:
            files = self.request.form.get("file", [])
        elif "file[]" in self.request.form:
            files = self.request.form.get("file[]", [])

        if not isinstance(files, (list, tuple)):
            files = [files]

        result = {}

        for cnt, filedata in enumerate(files):
            filename = filedata.filename
            content_type = mimetypes.guess_type(filename)[0] or ""

            ctr = getToolByName(self.context, "content_type_registry")
            type_ = ctr.findTypeName(filename.lower(), content_type, "") or "Image"

            # Now check that the object is not restricted to be added in the
            # current context
            allowed_ids = [fti.getId() for fti in self.context.allowedContentTypes()]
            if type_ not in allowed_ids:
                response = self.request.RESPONSE
                response.setStatus(403)
                return _(
                    "image_upload_not_allowed",
                    "You cannot add this Image to this folder. Try another one.",
                )

            obj = IDXFileFactory(self.context)(filename, content_type, filedata)

            result[f"file-{cnt}"] = {
                "url": f"{obj.absolute_url()}/@@images/image/3col",
                "id": IUUID(obj),
            }

        self.request.response.setHeader(
            "Content-Type", "application/json; charset=utf-8"
        )
        return json.dumps(result)


class InWorkspace(BrowserView):
    def __call__(self):
        """True if context is within a workspace"""
        return in_workspace(self.context)


class PloneintranetEnabled(BrowserView):
    def __call__(self):
        """This view is used to check whether the Ploneintranet theme is enabled.
        Use it as follows:
            <div tal:condition="exists: here/@@ploneintranet_enabled">...</div>
            <div tal:condition="not: exists: here/@@ploneintranet_enabled">...</div>
        """
        return "ok"
