##############################################################################
#
#    ICU Format, a module for Odoo
#    Copyright © 2021, 2022 XCG Consulting (https://xcg-consulting.fr/)
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import datetime
import logging
from typing import Dict, Mapping, Union

from icu import ICUError

from odoo import _, models

from ..icu_format import ICUFormatter, _icu_formatter_cache, icu_format, icu_list_format

_logger = logging.getLogger(__name__)


class BaseModel(models.AbstractModel):
    """Add methods to BaseModel to use icu formatting."""

    _inherit = "base"

    def icu_format_locale_kwargs(self) -> Mapping[str, str]:
        """Hook for some model to inject some information into the locale
        kwargs dict"""
        return {}

    def icu_format(
        self,
        msg: str,
        args: Dict[str, Union[int, str, datetime.date, datetime.datetime, bool, float]],
        raise_exception: bool = False,
    ) -> str:
        """Provide a faster way to format the message, using the context lang,
        or the user lang if there is no context.
        """
        return icu_format(
            self.env.context.get("lang") or self.env.user.lang,
            msg,
            args,
            raise_exception,
            locale_kwargs=self.icu_format_locale_kwargs(),
        )

    def icu_format_translate(
        self,
        untranslated_message: str,
        args: Dict[str, Union[int, str, datetime.date, datetime.datetime, bool, float]],
        raise_exception: bool = False,
    ) -> str:
        """Try to format and translate a message.
        If the format of the translated message fails, try to format the
        original message.
        """
        msg = _(untranslated_message)
        try:
            return icu_format(
                self.env.context.get("lang") or self.env.user.lang,
                msg,
                args,
                raise_exception=True,
                locale_kwargs=self.icu_format_locale_kwargs(),
            )
        except ICUError:
            _logger.error(
                "Error building message '%s'. Trying untranslated version",
                msg,
                exc_info=True,
            )
            return icu_format(
                "C",
                untranslated_message,
                args,
                raise_exception,
                locale_kwargs=self.icu_format_locale_kwargs(),
            )

    def icu_list_format(self, list_data: list) -> str:
        return icu_list_format(
            self.env.context.get("lang") or self.env.user.lang, list_data
        )

    def get_icu_formatter(self, message: str) -> ICUFormatter:
        return _icu_formatter_cache.get(
            message,
            self.env.context.get("lang") or self.env.user.lang,
            locale_kwargs=self.icu_format_locale_kwargs(),
        )