from plone import api
from plone.memoize.view import memoize
from plone.memoize.view import memoize_contextless
from ploneintranet.core import _
from ploneintranet.layout.browser.base import BasePanel
from Products.Five import BrowserView


class TranslationsView(BrowserView):
    """Some helpers meant to be used in page templates or other views"""

    @property
    @memoize
    def can_add_translation(self):
        """Check if the user can add a translation"""
        return api.user.has_permission("Add portal content", obj=self.context.aq_parent)

    @property
    @memoize
    def can_delete_translation(self):
        """Check if the user can remove a translation"""
        return api.user.has_permission("Delete objects", obj=self.context)

    @property
    @memoize_contextless
    def portal_languages(self):
        return api.portal.get_tool("portal_languages")

    @property
    @memoize_contextless
    def default_language(self) -> str:
        """Return the default language."""
        return api.portal.get_default_language()

    @property
    @memoize_contextless
    def available_language_codes(self) -> list[str]:
        """Return a list of available language codes"""
        return self.portal_languages.settings.available_languages

    def code2name(self, code: str) -> str:
        """Take a language code and return is name

        e.g. 'it' -> 'Italian' or 'Italiano' depending on the language settings
        """
        return api.portal.translate(
            self.portal_languages.getNameForLanguageCode(code),
            domain="ploneintranet",
        )

    def get_obj_language_code(self, obj=None):
        """Get the language code for the given object.
        If not present assume the portal default.
        """
        if obj is None:
            obj = self.context
        return obj.Language() or self.default_language

    def get_obj_language_name(self, obj=None):
        code = self.get_obj_language_code(obj)
        return self.code2name(code)

    def get_translations(self, obj=None, restricted=False):
        """Return a list of existing translations for the given object,
        If the object is not specified, use the current context.

        The translations are sorted by the language name
        """
        # First check if this is the original document,
        # the translations are stored as relations in the `translations` attribute
        if obj is None:
            obj = self.context
        translations = list(
            filter(
                None,
                [translation.to_object for translation in obj.translations],
            )
        )
        if not translations:
            # Maybe this is a translation, check if it is referenced by other news
            sources = api.relation.get(target=obj, relationship="translations")
            # Sources is expected to be an empty or a one element list containing
            # the relation  to the original object
            for source in sources:
                original = source.from_object
                if original is not None:
                    # We add to the list of translations the original object
                    # and the translations it references
                    translations.append(original)
                    translations.extend(
                        [translation.to_object for translation in original.translations]
                    )
        # Remove the obsolete relations that might have been removed
        # and the current object
        # also if restricted is True, check is we have the permission to view the object
        return sorted(
            (
                translation
                for translation in translations
                if (
                    translation is not None
                    and translation != obj
                    and (
                        not restricted
                        or api.user.has_permission("View", obj=translation)
                    )
                )
            ),
            key=self.get_obj_language_name,
        )


class CreateLanguagePanel(BasePanel):

    title = _("Add a language")
    _form_data_pat_inject_parts = ("#document-body",)

    @property
    @memoize
    def translations_view(self):
        return api.content.get_view("translations_view", self.context, self.request)

    @property
    def allowed_languages(self):
        """Return a list of languages that are not yet used"""
        translations_view = self.translations_view
        default_language = translations_view.default_language
        current_language = translations_view.get_obj_language_code()

        # We allow translations only on the default language
        if current_language != default_language:
            return []

        available_languages = set(translations_view.available_language_codes)
        available_languages.remove(current_language)
        return available_languages - set(
            map(
                translations_view.get_obj_language_code,
                translations_view.get_translations(),
            )
        )

    def options(self) -> list[dict]:
        """Return the options as a list of dicts"""
        translations_view = self.translations_view
        return sorted(
            [
                {"value": code, "label": translations_view.code2name(code)}
                for code in self.allowed_languages
            ],
            key=lambda option: option["label"],
        )

    def execute_on_post(self):
        """On post we want to create a translation to this object"""
        if not self.translations_view.can_add_translation:
            # additional security check because the panel is rendered in the
            # context of a news item, not in the context of the news folder
            api.portal.show_message(
                _("You do not have the permission to add a translation"),
                self.request,
                type="error",
            )
            return self.request.response.redirect(
                f"{self.context.absolute_url()}/edit.html"
            )

        language = self.request.form.get("language")
        if language not in self.allowed_languages:
            api.portal.show_message(
                _("The language you selected is not available"),
                self.request,
                type="error",
            )
            return self.request.response.redirect(
                f"{self.context.absolute_url()}/edit.html"
            )

        target = api.content.copy(
            self.context,
            self.context.aq_parent,
            id=f"{self.context.getId()}-{language}",
            safe_id=True,
        )
        target.language = language
        target.translations = []
        api.relation.create(self.context, target, "translations")
        return self.request.response.redirect(f"{target.absolute_url()}/edit.html")


class RemoveLanguagePanel(BasePanel):
    title = _("Remove this language")
    _form_data_pat_inject_parts = ("#document-body",)

    def execute_on_post(self):
        if self.context.translations:
            api.portal.show_message(
                _("It seems that this content has translations"),
                self.request,
                type="error",
            )
            return self.request.response.redirect(
                f"{self.context.absolute_url()}/edit.html"
            )
        # where should we go next?
        target_url = None
        sources = api.relation.get(target=self.context, relationship="translations")
        for source in sources:
            obj = source.from_object
            if obj:
                target_url = self.request.response.redirect(
                    f"{obj.absolute_url()}/edit.html"
                )
                api.relation.delete(source=obj, target=self.context)
        if target_url is None:
            target_url = f"{api.portal.get().absolute_url()}/news/publisher"
        api.content.delete(self.context)
        return self.request.response.redirect(target_url)


# We do not have translation for languages in Plone, we only have native names
_("Abkhazian")
_("Afar")
_("Afrikaans")
_("Akan")
_("Albanian")
_("Amharic")
_("Arabic")
_("Aragonese")
_("Armenian")
_("Assamese")
_("Avestan")
_("Aymara")
_("Azerbaijani")
_("Bambara")
_("basa Jawa")
_("Bashkir")
_("Basque")
_("Belarussian")
_("Bengali")
_("Bihari")
_("Bislama")
_("Bosnian")
_("Breton")
_("Bulgarian")
_("Burmese")
_("Cambodian/Khmer")
_("Catalan")
_("Chamorro")
_("Chechen")
_("Chichewa")
_("Chinese")
_("Chuvash")
_("Cornish")
_("Corsican")
_("Cree")
_("Croatian")
_("Czech")
_("Danish")
_("Dutch")
_("English")
_("English (USA)")
_("Esperanto")
_("Estonian")
_("Ewe")
_("Faroese")
_("Fiji")
_("Finnish")
_("French")
_("Frisian")
_("Fula")
_("Galician")
_("Ganda")
_("Georgian")
_("German")
_("Greek")
_("Greenlandic")
_("Guarani")
_("Gujarati")
_("Haitian")
_("Hausa")
_("Hebrew")
_("Herero")
_("Hindi")
_("Hiri Motu")
_("Hungarian")
_("Icelandic")
_("Ido")
_("Igbo")
_("Indian Bhutani")
_("Indonesian")
_("Interlingua")
_("Interlingue")
_("Inuktitut")
_("Inupiak")
_("Irish Gaelic")
_("Italian")
_("Japanese")
_("Kannada")
_("Kanuri")
_("Kashmiri")
_("Kazakh")
_("Kikuyu")
_("Kinyarwanda")
_("Kirghiz")
_("Kirundi")
_("Komi")
_("Kongo")
_("Korean")
_("Kurdish")
_("Kwanyama")
_("Laotian")
_("Latin")
_("Latvian")
_("Limburgish")
_("Lingala")
_("Lithuanian")
_("Luba-Katanga")
_("Luxemburgish")
_("Macedonian")
_("Madagascarian")
_("Malay")
_("Malayalam")
_("Maldivian")
_("Maltese")
_("Manx Gaelic")
_("Maori")
_("Marathi")
_("Marshallese")
_("Moldavian")
_("Mongolian")
_("Nauruan")
_("Navajo")
_("Ndebele (North)")
_("Ndebele (South)")
_("Ndonga")
_("Nepali")
_("Northern Sámi")
_("Norwegian Bokmål")
_("Norwegian")
_("Nuosu")
_("Nynorsk")
_("Occitan")
_("Ojibwe")
_("Old Church Slavonic")
_("Oriya")
_("Oromo")
_("Ossetian")
_("Pāli")
_("Pashto")
_("Persian")
_("Polish")
_("Portuguese")
_("Punjabi")
_("Quechua")
_("Rhaeto-Romance")
_("Romanian")
_("Russian")
_("Samoan")
_("Sangho")
_("Sanskrit")
_("Sardinian")
_("Scottish Gaelic")
_("Serbian")
_("Serbo-Croatian")
_("Shona")
_("Sindhi")
_("Singhalese")
_("Slovak")
_("Slovenian")
_("Somali")
_("Southern Sotho")
_("Spanish")
_("Sudanese")
_("Swahili")
_("Swati")
_("Swedish")
_("Tadjik")
_("Tagalog")
_("Tahitian")
_("Tamil")
_("Tatar")
_("Telugu")
_("Thai")
_("Tibetan")
_("Tigrinya")
_("Tonga")
_("Tsonga")
_("Tswana")
_("Turkish")
_("Turkmen")
_("Twi")
_("Uigur")
_("Ukrainian")
_("Urdu")
_("Uzbek")
_("Venda")
_("Vietnamese")
_("Viking")
_("Volapük")
_("Walloon")
_("Welsh")
_("Wolof")
_("Xhosa")
_("Yiddish")
_("Yorouba")
_("Zhuang")
_("Zulu")
