#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import (unicode_literals, division, absolute_import, print_function)

import traceback
from calibre.ebooks.metadata.sources.base import Source
from calibre.utils.config_base import tweaks

#
# Hack to get data from the Overdrive Link plugin. Will fail if not already installed.
#
from calibre_plugins.overdrive_link import ActionOverdriveLink
from calibre_plugins.overdrive_link.link import (ODLinkSet, IDENT_AVAILABLE_LINK, IDENT_PURCHASABLE_LINK)
from calibre_plugins.overdrive_link.tweak import (TWEAK_MAX_BOOK_PANEL_LINKS)

from .python_transition import (IS_PYTHON2)
if IS_PYTHON2:
    from .python_transition import (str)


'''
Allow links to lending library books to be followed from the book details panel
'''

__license__ = 'GPL v3'
__copyright__ = '2012-2025, John Howell <jhowell@acm.org>'


class OverdriveLinkMetadata(Source):
    name = ActionOverdriveLink.name + ' Metadata Source'
    description = 'Allows links set by this plugin to be shown in the book details panel'
    author = ActionOverdriveLink.author
    version = ActionOverdriveLink.version
    minimum_calibre_version = ActionOverdriveLink.minimum_calibre_version

    def __init__(self, plugin_path, plugin_action):
        Source.__init__(self, plugin_path)
        self.plugin_action = plugin_action

    def get_book_urls(self, identifiers):
        '''
        Override this method if you would like to return multiple urls for this book.
        Return a list of 3-tuples. By default this method simply calls :method:`get_book_url`.
        '''
        # New in calibre 2.19.0

        retval = []

        try:
            odid = '&'.join([s for s in [identifiers.get(IDENT_AVAILABLE_LINK), identifiers.get(IDENT_PURCHASABLE_LINK)] if s])

            if odid:
                max_book_pane_links = tweaks.get(TWEAK_MAX_BOOK_PANEL_LINKS, 10)
                if max_book_pane_links > 0:
                    for i, odlink in enumerate(ODLinkSet(odid, config=self.plugin_action.config).sorted_odlinks()):
                        if i < max_book_pane_links:
                            retval.append((IDENT_AVAILABLE_LINK, str(odlink), odlink.url()))
                        else:
                            retval[-1] = (IDENT_AVAILABLE_LINK, '&'.join([retval[-1][1], str(odlink)]), retval[-1][2])  # append excess links to last

        except Exception:
            # For testing. This keeps the above code from failing invisibly.
            traceback.print_exc()

        return retval

    def get_book_url(self, identifiers):
        '''
        Return a 3-tuple or None. The 3-tuple is of the form:
        (identifier_type, identifier_value, URL).
        The URL is the URL for the book identified by identifiers at this
        source. identifier_type, identifier_value specify the identifier
        corresponding to the URL.
        This URL must be browseable to by a human using a browser. It is meant
        to provide a clickable link for the user to easily visit the books page
        at this source.
        If no URL is found, return None. This method must be quick, and
        consistent, so only implement it if it is possible to construct the URL
        from a known scheme given identifiers.

        The identifier may contain multiple links. Just use the highest priority.
        '''

        try:
            odid = identifiers.get(IDENT_AVAILABLE_LINK, '')
            if odid:
                return (IDENT_AVAILABLE_LINK, odid, ODLinkSet(odid, config=self.plugin_action.config).primary_odlink().url())
        except Exception:
            # For testing. This keeps the above code from failing invisibly.
            traceback.print_exc()

        return None

    def get_book_url_name(self, idtype, idval, url):
        '''
        Return a human readable name from the return value of get_book_url().
        Indicate whether additional links are available with a '+' suffix on the name.
        '''
        try:
            if idtype == IDENT_AVAILABLE_LINK:
                odlinkset = ODLinkSet(idval, config=self.plugin_action.config)
                return '%s%s' % (odlinkset.primary_odlink().format_and_name(), '+' if len(odlinkset) > 1 else '')

        except Exception:
            # For testing. This keeps the above code from failing invisibly.
            traceback.print_exc()

        return idtype  # This shouldn't happen, but show something reasonable just in case

    def is_customizable(self):
        return False
