from AccessControl import getSecurityManager
from Acquisition import aq_parent
from plone.app.multilingual import _
from plone.app.multilingual.browser.interfaces import ITranslateMenu
from plone.app.multilingual.browser.interfaces import ITranslateSubMenuItem
from plone.app.multilingual.browser.utils import is_language_independent
from plone.app.multilingual.browser.vocabularies import translated_languages
from plone.app.multilingual.browser.vocabularies import translated_urls
from plone.app.multilingual.browser.vocabularies import untranslated_languages
from plone.app.multilingual.interfaces import ILanguageRootFolder
from plone.app.multilingual.interfaces import IMultiLanguageExtraOptionsSchema
from plone.app.multilingual.interfaces import IPloneAppMultilingualInstalled
from plone.app.multilingual.interfaces import ITG
from plone.app.multilingual.interfaces import ITranslatable
from plone.app.multilingual.interfaces import LANGUAGE_INDEPENDENT
from plone.app.multilingual.permissions import ManageTranslations
from plone.base.defaultpage import is_default_page
from plone.base.interfaces import ILanguage
from plone.base.utils import safe_text
from plone.memoize import view
from plone.registry.interfaces import IRegistry
from Products.CMFCore.utils import getToolByName
from zope.browsermenu.menu import BrowserMenu
from zope.browsermenu.menu import BrowserSubMenuItem
from zope.component import getUtility
from zope.component.hooks import getSite
from zope.interface import implementer


@implementer(ITranslateMenu)
class TranslateMenu(BrowserMenu):
    def getMenuItems(self, context, request):
        """Return menu item entries in a TAL-friendly form."""
        # Settings
        site_url = getSite().absolute_url()
        language_tool = getToolByName(context, "portal_languages")
        show_flags = language_tool.showFlags
        try:
            lang_names = request.locale.displayNames.languages
        except AttributeError:
            lang_names = {}

        registry = getUtility(IRegistry)
        settings = registry.forInterface(
            IMultiLanguageExtraOptionsSchema, prefix="plone"
        )
        if settings.redirect_babel_view:
            translation_view = "babel_edit"
        else:
            translation_view = "edit"

        # Content
        content = context
        content_url = context.absolute_url()
        content_language = ILanguage(content).get_language()
        content_translatable = not (
            content_language == LANGUAGE_INDEPENDENT
            or is_language_independent(content)
            or ILanguageRootFolder.providedBy(content)
        )
        content_translated = translated_languages(content)
        content_untranslated = untranslated_languages(content)
        content_translation_group = ITG(content, "")
        if not ITranslatable.providedBy(content):
            content = None

        # Folder when content is default page
        folder = aq_parent(context)
        if not is_default_page(folder, context):
            folder = None
        if folder and ITranslatable.providedBy(folder):  # noqa
            folder_url = folder.absolute_url()
            folder_language = ILanguage(folder).get_language()
            folder_translatable = not (
                folder_language == LANGUAGE_INDEPENDENT
                or is_language_independent(folder)
                or ILanguageRootFolder.providedBy(folder)
            )
            folder_translated = translated_languages(folder)
            folder_untranslated = untranslated_languages(folder)
            folder_translation_group = ITG(folder, "")
        else:
            folder_url = ""
            folder_language = ""
            folder_translatable = False
            folder_translated = []
            folder_untranslated = []
            folder_translation_group = ""

        # Assets folder
        assets_folder_url = None
        assets_folder_title = None
        pc = getToolByName(getSite(), "portal_catalog")
        results = pc.unrestrictedSearchResults(
            portal_type="LIF", Language=ILanguage(context).get_language()
        )
        for brain in results:
            assets_folder_url = brain.getURL() + "/folder_contents"
            assets_folder_title = safe_text(brain.Title)
            break
        # Menu items
        results = []
        results_folder = []
        results_content = []

        if folder_translatable:
            # Folder translation view
            lang_name = lang_names.get(folder_language, folder_language)
            results_folder.append(
                {
                    "title": _(
                        "edit_translation",
                        default="Edit ${lang_name}",
                        mapping={"lang_name": lang_name},
                    ),
                    "description": _(
                        "description_babeledit_menu",
                        default="Edit {lang_name} with the two-column translation view",  # noqa
                        mapping={"lang_name": lang_name},
                    ),
                    "action": folder_url + "/" + translation_view,
                    "selected": False,
                    "icon": None,
                    "extra": {
                        "id": "_edit_folder_babel_edit",
                        "separator": None,
                        "class": "",
                    },
                    "submenu": None,
                }
            )

        if (
            folder and folder_untranslated and False
        ):  # disabled in favor of cut & paste  # noqa
            # Set folder language
            results_folder.append(
                {
                    "title": _("title_set_language", default="Change content language"),
                    "description": _(
                        "description_set_language",
                        default="Move the translation under another language folder",  # noqa
                    ),
                    "action": folder_url + "/update_language",
                    "selected": False,
                    "icon": None,
                    "extra": {
                        "id": "_set_folder_language",
                        "separator": None,
                        "class": "",
                    },
                    "submenu": None,
                }
            )

        if folder_translatable:
            for idx, lang in enumerate(folder_untranslated):
                lang_name = lang_names.get(lang.value, lang.title)
                lang_id = lang.value
                icon = (
                    show_flags and language_tool.getFlagForLanguageCode(lang_id) or None
                )  # noqa
                results_folder.append(
                    {
                        "title": _(
                            "create_translation",
                            default="Create ${lang_name}",
                            mapping={"lang_name": lang_name},
                        ),
                        "description": _(
                            "description_translate_into",
                            default="Translate into ${lang_name}",
                            mapping={"lang_name": lang_name},
                        ),
                        "action": "%s/@@create_translation?language=%s"
                        % (folder_url, lang_id),
                        "selected": False,
                        "icon": icon,
                        "width": "14",
                        "height": "11",
                        "extra": {
                            "id": "translate_folder_into_%s" % lang_id,
                            "separator": None,
                            "class": "contentmenuflags",
                        },
                        "submenu": None,
                    }
                )
            urls = translated_urls(folder)
            for lang in folder_translated:
                if lang.value not in urls.by_token:
                    # omit if translation is not permitted to access.
                    continue
                lang_name = lang_names.get(lang.value, lang.title)
                lang_id = lang.value
                icon = (
                    show_flags and language_tool.getFlagForLanguageCode(lang_id) or None
                )  # noqa
                results_folder.append(
                    {
                        "title": _(
                            "edit_translation",
                            default="Edit ${lang_name}",
                            mapping={"lang_name": lang_name},
                        ),
                        "description": _(
                            "description_babeledit_menu",
                            default="Edit {lang_name} with the two-column translation view",  # noqa
                            mapping={"lang_name": lang_name},
                        ),
                        "action": (
                            urls.getTerm(lang_id).title + "/" + translation_view
                        ),
                        "selected": False,
                        "icon": icon,
                        "width": "14",
                        "height": "11",
                        "extra": {
                            "id": "babel_edit_%s" % lang_id,
                            "separator": None,
                            "class": "contentmenuflags",
                        },
                        "submenu": None,
                    }
                )
            # Manage folder translations
            results_folder.append(
                {
                    "title": _(
                        "title_modify_translations", default="Manage translations"
                    ),
                    "description": _(
                        "description_modify_translations",
                        default="Add or delete translations",
                    ),
                    "action": folder_url + "/modify_translations",
                    "selected": False,
                    "icon": None,
                    "extra": {
                        "id": "_modify_folder_translations",
                        "separator": None,
                        "class": "",
                    },
                    "submenu": None,
                }
            )
            # Universal link
            if folder_translation_group:
                results_folder.append(
                    {
                        "title": _("universal_link", default="Universal link"),
                        "description": _(
                            "description_universal_link",
                            default="Universal link to the content in user's preferred language",  # noqa
                        ),
                        "action": "%s/@@multilingual-universal-link/%s"
                        % (site_url, folder_translation_group),
                        "selected": False,
                        "icon": None,
                        "extra": {
                            "id": "_universal_folder_link",
                            "separator": None,
                            "class": "",
                        },
                        "submenu": None,
                    }
                )

        if results_folder:
            # Folder translation separator
            results.append(
                {
                    "title": _(
                        "title_translate_current_folder", default="Folder translation"
                    ),
                    "description": "",
                    "action": None,
                    "selected": False,
                    "icon": None,
                    "extra": {
                        "id": "translateFolderHeader",
                        "separator": "actionSeparator",
                        "class": "plone-toolbar-submenu-header",
                    },
                    "submenu": None,
                }
            )
        results.extend(results_folder)

        lang_name = lang_names.get(content_language, content_language)

        # Content language
        if content_untranslated and False:  # disabled in favor of cut & paste
            results_content.append(
                {
                    "title": _("title_set_language", default="Change content language"),
                    "description": _(
                        "description_set_language",
                        default="Move the translation under another language folder",  # noqa
                    ),
                    "action": content_url + "/update_language",
                    "selected": False,
                    "icon": None,
                    "extra": {"id": "_set_language", "separator": None, "class": ""},
                    "submenu": None,
                }
            )

        if content_translatable:
            # Content translation view
            results_content.append(
                {
                    "title": _(
                        "edit_translation",
                        default="Edit ${lang_name}",
                        mapping={"lang_name": lang_name},
                    ),
                    "description": _(
                        "description_babeledit_menu",
                        default="Edit {lang_name} with the two-column translation view",  # noqa
                        mapping={"lang_name": lang_name},
                    ),
                    "action": content_url + "/" + translation_view,
                    "selected": False,
                    "icon": None,
                    "extra": {
                        "id": "_edit_babel_edit",
                        "separator": None,
                        "class": "",
                    },
                    "submenu": None,
                }
            )

        if content_translatable:
            for idx, lang in enumerate(content_untranslated):
                lang_name = lang_names.get(lang.value, lang.title)
                lang_id = lang.value
                icon = (
                    show_flags and language_tool.getFlagForLanguageCode(lang_id) or None
                )  # noqa
                results_content.append(
                    {
                        "title": _(
                            "create_translation",
                            default="Create ${lang_name}",
                            mapping={"lang_name": lang_name},
                        ),
                        "description": _(
                            "description_translate_into",
                            default="Translate into ${lang_name}",
                            mapping={"lang_name": lang_name},
                        ),
                        "action": "%s/@@create_translation?language=%s"
                        % (content_url, lang_id),
                        "selected": False,
                        "icon": icon,
                        "width": "14",
                        "height": "11",
                        "extra": {
                            "id": "translate_into_%s" % lang_id,
                            "separator": None,
                            "class": "contentmenuflags",
                        },
                        "submenu": None,
                    }
                )
            urls = translated_urls(content)
            for lang in content_translated:
                if lang.value not in urls.by_token:
                    # omit if translation is not permitted to access.
                    continue
                lang_name = lang_names.get(lang.value, lang.title)
                lang_id = lang.value
                icon = (
                    show_flags and language_tool.getFlagForLanguageCode(lang_id) or None
                )  # noqa
                results_content.append(
                    {
                        "title": _(
                            "edit_translation",
                            default="Edit ${lang_name}",
                            mapping={"lang_name": lang_name},
                        ),
                        "description": _(
                            "description_babeledit_menu",
                            default="Edit {lang_name} with the two-column translation view",  # noqa
                            mapping={"lang_name": lang_name},
                        ),
                        "action": (
                            urls.getTerm(lang_id).title + "/" + translation_view
                        ),
                        "selected": False,
                        "icon": icon,
                        "width": "14",
                        "height": "11",
                        "extra": {
                            "id": "babel_edit_%s" % lang_id,
                            "separator": None,
                            "class": "contentmenuflags",
                        },
                        "submenu": None,
                    }
                )
            # Manage content translations
            results_content.append(
                {
                    "title": _(
                        "title_modify_translations", default="Manage translations"
                    ),
                    "description": _(
                        "description_modify_translations",
                        default="Add or delete translations",
                    ),
                    "action": content_url + "/modify_translations",
                    "selected": False,
                    "icon": None,
                    "extra": {
                        "id": "_modify_translations",
                        "separator": None,
                        "class": "",
                    },
                    "submenu": None,
                }
            )
            # Universal link
            if content_translation_group:
                results_content.append(
                    {
                        "title": _("universal_link", default="Universal link"),
                        "description": _(
                            "description_universal_link",
                            default="Universal link to the content in user's preferred language",  # noqa
                        ),
                        "action": "%s/@@multilingual-universal-link/%s"
                        % (site_url, content_translation_group),
                        "selected": False,
                        "icon": None,
                        "extra": {
                            "id": "_universal_link",
                            "separator": None,
                            "class": "",
                        },
                        "submenu": None,
                    }
                )

        if results_folder and results_content:
            # Item translations separator
            results.append(
                {
                    "title": _(
                        "title_translate_current_item", default="Item translation"
                    ),
                    "description": "",
                    "action": None,
                    "selected": False,
                    "icon": None,
                    "extra": {
                        "id": "translateItemHeader",
                        "separator": "actionSeparator",
                        "class": "",
                    },
                    "submenu": None,
                }
            )
        results.extend(results_content)

        # Language independent assets folder
        if assets_folder_url:
            results.append(
                {
                    "title": _(
                        "shared_folder",
                        default="Open ${title} folder",
                        mapping={"title": assets_folder_title},
                    ),
                    "description": _(
                        "description_shared_folder",
                        default="Open the language independent assets folder",
                    ),
                    "action": assets_folder_url,
                    "selected": False,
                    "icon": None,
                    "extra": {
                        "id": "_shared_folder",
                        "separator": results and "actionSeparator" or None,
                        "class": "",
                    },
                    "submenu": None,
                }
            )

        # User preferred language root folder
        if not folder_translatable and not content_translatable:
            results.append(
                {
                    "title": _("language_folder", default="Return to language folder"),
                    "description": _(
                        "description_language_folder",
                        default="Go to the user's browser preferred language "
                        "related folder",
                    ),
                    "action": site_url
                    + "/"
                    + language_tool.getPreferredLanguage(),  # noqa
                    "selected": False,
                    "icon": None,
                    "extra": {
                        "id": "_language_folder",
                        "separator": (
                            (results and not assets_folder_url)
                            and "actionSeparator"
                            or None
                        ),
                        "class": "",
                    },
                    "submenu": None,
                }
            )

        return results


@implementer(ITranslateSubMenuItem)
class TranslateSubMenuItem(BrowserSubMenuItem):
    title = _("label_translate_menu", default="Translate")
    description = _(
        "title_translate_menu", default="Manage translations for your content."
    )
    submenuId = "plone_contentmenu_multilingual"
    order = 5

    @property
    def action(self):
        return self.context.absolute_url() + "/add_translations"

    @property
    def extra(self):
        return {
            "id": "plone-contentmenu-multilingual",
            "li_class": "plonetoolbar-multilingual",
        }

    @view.memoize
    def available(self):
        # Is PAM installed?
        if not IPloneAppMultilingualInstalled.providedBy(self.request):
            return False

        # Do we have portal_languages?
        lt = getToolByName(self.context, "portal_languages", None)
        if lt is None:
            return False

        # Do we have multiple languages?
        supported = lt.listSupportedLanguages()
        if len(supported) < 2:
            return False

        # And now check permissions
        sm = getSecurityManager()
        if not sm.checkPermission(ManageTranslations, self.context):
            return False

        return True

    def selected(self):
        return False
