from __future__ import annotations

import param
from panel.widgets.misc import FileDownload as _FileDownload

from ..base import ThemedTransform
from .base import TooltipTransform
from .button import _ButtonBase


class FileDownload(_ButtonBase, _FileDownload):
    """
    The `FileDownload` widget allows a user to download a file.

    It works either by sending the file data to the browser on initialization
    (`embed`=True), or when the button is clicked.

    :References:

    - https://panel-material-ui.holoviz.org/reference/widgets/FileDownload.html
    - https://panel.holoviz.org/reference/widgets/FileDownload.html
    - https://mui.com/material-ui/react-button/

    :Example:

    >>> FileDownload(file='IntroductionToPanel.ipynb', filename='intro.ipynb')
    """

    icon_size = param.String(default="1em", doc="""
        Size of the icon as a string, e.g. 12px or 1em.""")

    _syncing = param.Boolean(default=False, doc="""
        If `auto` is False track syncing data state.""")

    _esm_base = "FileDownload.jsx"
    _esm_transforms = [TooltipTransform, ThemedTransform]
    _rename = {
        "_clicks": None, "icon": "icon", "icon_size": "icon_size", "description": "description"
    }
    _source_transforms = {
        "button_type": None, "button_style": None, "callback": None,
        "file": None, "value": None, "attached": None
    }

    def __init__(self, file=None, **params):
        self._default_label = 'label' not in params
        self._synced = False
        super().__init__(file=file, **params)

    def transfer(self, download: bool = False):
        """
        Transfers current data to the frontend.

        Parameters
        ----------
        download: bool
            If True, the data will automatically be downloaded
            once the data is transferred.
        """
        with self.param.update(auto=download):
            self._transfer()

    def _handle_click(self, event=None):
        self._clicks += 1

    @param.depends('auto', 'file', 'filename', '_syncing', watch=True)
    def _update_label(self):
        label = 'Download' if self._synced or self.auto else 'Fetching' if self._syncing else 'Fetch'
        if self._default_label:
            if self.file is None and self.callback is None:
                label = 'No file set'
            else:
                try:
                    filename = self.filename or self._file_path.name
                except TypeError:
                    raise ValueError('Must provide filename if file-like '
                                     'object is provided.') from None
                label = f'{label} {filename}'
            self.label = label
            self._default_label = True

    def _sync_data(self, fileobj):
        with self.param.update(_syncing=True):
            super()._sync_data(fileobj)


__all__ = [
    "FileDownload"
]
