# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
#
# Copyright (C) 2015 - 2018 David Mohammed <fossfreedom@ubuntu.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.

from gi.repository import GObject
from gi.repository import Gio
from gi.repository import Gtk

from alttoolbar_preferences import CoverLocale


class AltControllerCategory(object):
    OTHER = 0
    LOCAL = 1
    ONLINE = 2
    PLAYLIST = 3


class AltControllerBase(GObject.Object):
    """
    base controller
    """

    def __init__(self, header):
        """
        Initialises the object.
        """
        self.header = header
        self.find = self.header.find  # convenience function

        self._pixbuf = None

        super(AltControllerBase, self).__init__()

    def get_category(self):
        """
           return the category type for the source
        """

        return AltControllerCategory.OTHER

    def toolbar_visibility(self):
        """
            return the toolbar visibility
              by default None which means user controlled
        """

        return None

    def get_gicon(self, source):
        """
          return the source icon
        :param source:
        :return:
        """

        if source.props.icon:
            return source.props.icon

        return None

    def valid_source(self, source):
        """
          returns bool if the given source is applicable to the controller
        """

        return False

    def update_controls(self, source):
        """
           update the button controls on the header
        """

        pass

    def remove_controls(self, container):
        """
          remove any controls that are contained in a container
        """
        for child in container.get_children():
            container.remove(child)

    def hide_controls(self, source):
        """
          hide controls for a given controller
        """

        pass

    def get_search_entry(self, toolbar_container):
        """
          find the GtkEntry field corresponding to the search entry
          returns 1. the GtkWidget containing the GtkEntry
                  2. the GtkEntry
          returns None if nothing found
        """

        return None

    def get_toolbar(self, source):
        """
          return GtkWidget corresponding to the toolbar within the source
                 None if no toolbar
        """

        return None

    def moveto_searchbar(self, toolbar, widget, searchbar):
        """
          move from toolbar the widget and add to the searchbar
        """

        pass

    def set_library_labels(self):
        """
          set the centre library song-category button label
        """

        self.header.set_library_labels()


class AltGenericController(AltControllerBase):
    """
    generic controller for the headerbar (only)
    """
    __gtype_name = 'AltGenericController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltGenericController, self).__init__(header)

        self.centre_controls = {}
        self.end_controls = {}

    def get_category(self):
        return AltControllerCategory.LOCAL

    def hide_controls(self, source):
        val, view_button = self.header.has_button_with_label(source,
                                                             _('View All'))

        if val:
            view_button.set_visible(False)

    def get_toolbar(self, source):

        toolbar = self.find(source, 'RBSourceToolbar', 'by_name')
        print(toolbar)
        print(source)

        return toolbar

    def get_search_entry(self, container):
        if container is None:
            print("no container to search")
            return None, None
        search = self.find(container, 'RBSearchEntry', 'by_name')

        if not search:
            print("no RBSearchEntry found")
            return None, None

        entry = self.find(search, 'GtkEntry', 'by_name')
        print(entry)
        return search, entry

    def moveto_searchbar(self, toolbar, search, searchbar):
        toolbar.remove(search)
        toolbar.set_visible(False)

        searchbar.add(search)

    def update_controls(self, source):
        """
           update the button controls on the header
        """

        val, browser_button = self.header.is_browser_view(source)
        if not val:
            # if not a browser_view based source then default just to the title
            print("no browser view")
            self.header.set_library_box_sensitive(False)
        else:
            print("browser view found")
            browser_button.set_visible(False)
            self.header.set_library_box_sensitive(True)

        self.header.current_search_button = None

        toolbar = self.get_toolbar(source)
        if not toolbar:
            # there is no source-bar so the header is empty
            print("no toolbar so nothing left to do - cleanup endbox and exit")
            self.remove_controls(self.header.end_box)
            return

        self.hide_controls(toolbar)

        if source not in self.end_controls:
            # this is the first time for the source so extract the
            # RBSearchEntry
            print("first time around")
            controls = {}

            self.remove_controls(self.header.end_box)

            print(toolbar)  # should be the RBSourceToolbar
            search, entry = self.get_search_entry(toolbar)
            if not search:
                return

            if self.header.searchbar:
                self.header.searchbar.set_visible(False)

            # define a searchbar widget
            self.header.searchbar = Gtk.SearchBar.new()

            # we need to add this to the top of the source window
            # to-do this - find the first child and physically move this into
            # the second position in a box - the first position being the
            # searchbar
            children = source.get_children()
            print(children)
            # We assume the first container in a source is a GtkNotebook
            first = children[0]
            box = Gtk.Box()
            box.set_orientation(Gtk.Orientation.VERTICAL)
            box.pack_start(self.header.searchbar, False, True, 0)
            box.show_all()
            # so remove the notebook from the source
            Gtk.Container.remove(source, first)
            box.pack_start(first, True, True, 1)  # add the notebook to a box

            source.add(box)  # then add the box back to the source -
            # i.e. we added another parent

            self.header.register_moved_control(child=first,
                                               old_parent=source,
                                               new_parent=box)

            self.moveto_searchbar(toolbar, search, self.header.searchbar)
            entry.set_size_request(300, -1)

            self.header.searchbar.connect_entry(entry)
            # self.header.searchbar.show_all()
            self.header.searchbar.set_visible(False)

            search_button = Gtk.ToggleButton.new()
            sym = "preferences-system-search-symbolic"
            image = \
                Gtk.Image.new_from_icon_name(sym, Gtk.IconSize.SMALL_TOOLBAR)
            search_button.add(image)

            self.header.end_box.add(search_button)
            self.header.end_box.reorder_child(search_button, 0)
            search_button.show_all()
            search_button.connect('toggled', self.header.search_button_toggled)

            controls['searchbar'] = self.header.searchbar
            controls['search_button'] = search_button
            self.header.current_search_button = search_button
            self.end_controls[source] = controls
            print(controls)
        else:
            print("second time around")
            print(self.end_controls[source])
            search = self.end_controls[source]['searchbar']
            if self.header.searchbar:
                self.header.searchbar.set_visible(False)
            self.header.searchbar = search
            # self.header.searchbar.set_visible(True)

            self.remove_controls(self.header.end_box)
            search_button = self.end_controls[source]['search_button']
            self.header.current_search_button = search_button

            self.header.searchbar.show_all()
            self.header.searchbar.set_visible(search_button.get_active())

            self.header.end_box.add(search_button)
            self.header.end_box.reorder_child(search_button, 0)
            self.header.end_box.show_all()


class AltMusicLibraryController(AltGenericController):
    """
    music library controller
    """
    __gtype_name = 'AltMusicLibraryController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltMusicLibraryController, self).__init__(header)

    def valid_source(self, source):
        """
          override
        """

        return "LibrarySource" in type(source).__name__

    def hide_controls(self, source):
        super(AltMusicLibraryController, self).hide_controls(source)

        val, import_button = self.header.has_button_with_label(source,
                                                               _('Import'))

        if val:
            import_button.set_visible(False)


class AltSoundCloudController(AltGenericController):
    """
    sound-cloud controller
    """
    __gtype_name = 'AltSoundCloudController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltSoundCloudController, self).__init__(header)

        self._has_toolbar = None

    def valid_source(self, source):
        """
          override
        """

        return "SoundCloud" in type(source).__name__

    def get_category(self):
        return AltControllerCategory.ONLINE

    def get_toolbar(self, source):
        if self._has_toolbar:
            return self._has_toolbar

        search_box = self.find(source, 'box1', 'by_id')

        self._has_toolbar = search_box
        return search_box

    def moveto_searchbar(self, toolbar, widget, searchbar):
        """
          override - here we want to actually remove the toolbar from the
          source so get the parent
        """

        parent_grid = toolbar.get_parent()
        parent_grid.remove(toolbar)
        searchbar.add(toolbar)

        self.header.register_moved_control(child=toolbar,
                                           old_parent=parent_grid,
                                           new_parent=searchbar)


class AltCoverArtBrowserController(AltGenericController):
    """
    CoverArtBrowser controller
    """
    __gtype_name = 'AltCoverArtBrowserController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltCoverArtBrowserController, self).__init__(header)

        self._has_toolbar = None

    def valid_source(self, source):
        """
          override
        """

        return "CoverArtBrowser" in type(source).__name__

    def get_category(self):
        return AltControllerCategory.LOCAL

    def get_toolbar(self, source):
        if not self._has_toolbar:
            search_box = self.find(source, 'toolbar', 'by_id')
            self._has_toolbar = search_box

        return self._has_toolbar

    def moveto_searchbar(self, toolbar, widget, searchbar):
        """
          override - here we want to actually remove the toolbar from the
          source so get the parent
        """

        parent_grid = toolbar.get_parent()
        parent_grid.remove(toolbar)
        searchbar.add(toolbar)
        searchbar.show_all()

        self.header.register_moved_control(child=toolbar,
                                           old_parent=parent_grid,
                                           new_parent=searchbar)

    def get_search_entry(self, toolbar):
        """
          override - use the GtkEntry in the coverartbrowser
        """

        entrysearch = self.find(toolbar, 'entry_search_alignment', 'by_id')
        entry = self.find(entrysearch, 'GtkEntry', 'by_name')

        return entrysearch, entry


class AltCoverArtPlaySourceController(AltGenericController):
    """
    CoverArtPlaySource controller
    """
    __gtype_name = 'AltCoverArtPlaySourceController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltCoverArtPlaySourceController, self).__init__(header)

        self._has_toolbar = None

    def valid_source(self, source):
        """
          override
        """

        return "CoverArtPlaySource" in type(source).__name__

    def get_category(self):
        return AltControllerCategory.LOCAL

    def get_toolbar(self, source):
        if not self._has_toolbar:
            self._has_toolbar = self.find(source, 'RBButtonBar', 'by_name')

        print("############", self._has_toolbar)
        return self._has_toolbar


class AltQueueController(AltGenericController):
    """
    RB QueueSource controller
    """
    __gtype_name = 'AltQueueController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltQueueController, self).__init__(header)

        self._gicon = Gio.ThemedIcon(name='audio-x-queue-symbolic')

    def valid_source(self, source):
        return "RBPlayQueueSource" in type(source).__name__

    def get_gicon(self, source):
        return self._gicon


class AltErrorsController(AltGenericController):
    """
    RB ErrorsSource controller
    """
    __gtype_name = 'AltErrorsController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltErrorsController, self).__init__(header)

        self._gicon = Gio.ThemedIcon(name='dialog-error-symbolic')

        self._source_types = ["RBImportErrorsSource",
                              "RBMissingFilesSource"]

    def valid_source(self, source):
        print(type(source).__name__)
        for source_type in self._source_types:
            if source_type in type(source).__name__:
                return True

    def get_category(self):
        return AltControllerCategory.LOCAL

    def get_gicon(self, source):
        return self._gicon


class AltRadioController(AltGenericController):
    """
    RB RadioSource controller
    """
    __gtype_name = 'AltRadioController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltRadioController, self).__init__(header)

        self._gicon = Gio.ThemedIcon(name='audio-radio-symbolic')

    def valid_source(self, source):
        return "RBIRadioSource" in type(source).__name__

    def get_gicon(self, source):
        return self._gicon

    def get_category(self):
        return AltControllerCategory.ONLINE

    def set_library_labels(self):
        self.header.set_library_labels(song_label=_('Stations'))

    def toolbar_visibility(self):
        return True # radio source the source toolbar is always shown


class AltLastFMController(AltGenericController):
    """
    RB LastFMSource controller
    """
    __gtype_name = 'AltLastFMController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltLastFMController, self).__init__(header)

        self._libre_gicon = Gio.ThemedIcon(name='librefm-symbolic')
        self._lastfm_gicon = Gio.ThemedIcon(name='lastfm-symbolic')

    def valid_source(self, source):
        return "RBAudioscrobblerProfilePage" in type(source).__name__

    def get_gicon(self, source):
        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.RB)

        if source.props.name == _("Libre.fm"):
            return self._libre_gicon
        else:
            return self._lastfm_gicon

    def get_category(self):
        return AltControllerCategory.ONLINE


class AltPlaylistController(AltGenericController):
    """
    playlist controller
    """
    __gtype_name = 'AltPlaylistController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltPlaylistController, self).__init__(header)

        self._static_gicon = \
            Gio.ThemedIcon(name='audio-x-playlist-symbolic')
        self._auto_gicon = \
            Gio.ThemedIcon(name='audio-x-playlist-automatic-symbolic')

        self._toprated_gicon = Gio.ThemedIcon(name='starred-symbolic')
        self._recentlyadded_gicon = \
            Gio.ThemedIcon(name='audio-x-playlist-recently-added-symbolic')
        self._recentlyplayed_gicon = \
            Gio.ThemedIcon(name='audio-x-playlist-recently-played-symbolic')

    def valid_source(self, source):
        """
          override
        """
        return "PlaylistSource" in type(source).__name__

    def get_gicon(self, source):
        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.RB)
        print(source.props.name)
        if source.props.name == _('My Top Rated') \
                or source.props.name == 'My Top Rated':
            return self._toprated_gicon

        if source.props.name == _('Recently Added') \
                or source.props.name == 'Recently Added':
            return self._recentlyadded_gicon

        if source.props.name == _('Recently Played') \
                or source.props.name == 'Recently Played':
            return self._recentlyplayed_gicon

        if "StaticPlaylistSource" in type(source).__name__:
            return self._static_gicon
        else:
            return self._auto_gicon

    def get_category(self):
        return AltControllerCategory.PLAYLIST


class AltPodcastController(AltGenericController):
    """
    podcast controller
    """
    __gtype_name = 'AltPodcastController'

    def valid_source(self, source):
        """
          override
        """
        return 'RBPodcastMainSource' in type(source).__name__

    def get_category(self):
        return AltControllerCategory.LOCAL

    def set_library_labels(self):
        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        self.header.set_library_labels(song_label=_('Podcasts'))

    def toolbar_visibility(self):
        return True # podcast source the source toolbar is always shown


class AltStandardOnlineController(AltGenericController):
    """
      standard controller where we dont need specific customisation
    """
    __gtype_name = 'AltStandardOnlineController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltStandardOnlineController, self).__init__(header)

        self._source_types = ['MagnatuneSource',
                              'RBGriloSource',
                              'RadioBrowserSource']

    def valid_source(self, source):

        print(type(source).__name__)
        for source_type in self._source_types:
            if source_type in type(source).__name__:
                return True

        return False

    def get_category(self):
        return AltControllerCategory.ONLINE


class AltStandardLocalController(AltGenericController):
    """
      standard controller where we dont need specific customisation
    """
    __gtype_name = 'AltStandardLocalController'

    def __init__(self, header):
        """
        Initialises the object.
        """
        super(AltStandardLocalController, self).__init__(header)

        self._source_types = ['RBMtpSource']

    def valid_source(self, source):

        print(type(source).__name__)
        for source_type in self._source_types:
            if source_type in type(source).__name__:
                return True

        return False

    def get_category(self):
        return AltControllerCategory.LOCAL


class AltAndroidController(AltGenericController):
    '''
    android controller
    '''
    __gtype_name = 'AltAndroidController'

    def valid_source(self, source):
        '''
          override
        '''
        return 'RBAndroidSource' in type(source).__name__

    def get_category(self):
        return AltControllerCategory.LOCAL
