from pygametk.color import Color
from pygametk.draw import crop
from pygametk.geometry import Rect
from pygametk.image import load_image

from pylaunchr.builder.factory import DialogFactory
from pylaunchr.builder.path import module_relative_path

from ..data import MpdPlayerStatusListener
from ..utils import get_player_status


class InfoDialogUpdater(MpdPlayerStatusListener):

    def __init__(self, dialog, context):
        self.status = get_player_status(context)
        self.coverfetcher = context.services["coverfetcher"].handler
        self.imagefilter = context.services["imagefilter"].handler
        self.dialog = dialog
        self.dialog.connect("dialog-finished", self._finish_dialog)

    def _update_background_image(self, image, current):
        def blur_callback(result, song):
            if "image" in result and self.status.current == song:
                shade = Color(0, 0, 0, 230)
                self.dialog.set_background_image(result["image"], shade)

        image_rect = Rect((0, 0), image.get_size())
        screen_rect = Rect((0, 0), self.dialog.size)

        cropped = crop(image, screen_rect.fit(image_rect))
        self.imagefilter.blur(cropped, 15, blur_callback, [current])

    def _fetch_image(self, current):
        albuminfo = {
            "artist": current.albumartist,
            "album": current.album,
            "file": current.file
        }

        def callback(result, song):
            if "filename" in result and self.status.current == song:
                image = load_image(result["filename"])

                self._update_background_image(image, song)

                image_holder = self.dialog.get_widget("image")
                image_holder.set(image)

        self.coverfetcher.fetch(albuminfo, callback, [current])

    def _clear_image(self):
        self.dialog.get_widget("image").clear()
        self.dialog.set_background_color(Color(0, 0, 0))

    def _update(self):
        if self.status.has_current_song():
            self._fetch_image(self.status.current)
        else:
            self.dialog.cancel()

    def init(self):
        self.status.add_listener(self)
        self._update()

    def current_changed(self, mpd_status, current):
        self._update()

    def _finish_dialog(self):
        self.status.remove_listener(self)


class MpdInfoDialogFactory(DialogFactory):

    def create(self, element, widget_registry):
        path = module_relative_path("info.xml")
        dialog = self.context.dialog_registry.dialog_from_file(path)

        updater = InfoDialogUpdater(dialog, self.context)
        dialog.connect("dialog-started", updater.init)

        return dialog
