# -*- coding: utf-8 -*-
# Elisa - Home multimedia server
# Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Elisa with Fluendo's plugins.
#
# The GPL part of Elisa is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Elisa" in the root directory of this distribution package
# for details on that license.


__maintainer__ = 'Lionel Martin <lionel@fluendo.com>'
__maintainer2__ = 'Philippe Normand <philippe@fluendo.com>'


from elisa.base_components.view import View
from elisa.core import player, common, plugin_registry

from elisa.extern.translation import gettexter, N_, Translatable
T_ = gettexter('elisa-gtk-frontend')

import pygtk
pygtk.require('2.0')
import gtk

import pygst
pygst.require('0.10')
import gst
import gst.interfaces
import platform


class ViewerWidget(gtk.DrawingArea):
    """
    Code generously donated by Edward Hervey
    GTK Widget properly displaying GStreamer video sink
    """

    __gsignals__ = {}

    def __init__(self):
        gtk.DrawingArea.__init__(self)
        self.videosink = None
        self.have_set_xid = False
        self.can_set_xid = False
        self.unset_flags(gtk.DOUBLE_BUFFERED)
        self.unset_flags(gtk.SENSITIVE)


    def do_expose_event(self, unused_event):
        """ 'expose-event' override """
        if self.videosink:
            if not self.have_set_xid and self.can_set_xid:
                self.set_xwindow_id()
            elif self.have_set_xid:
                self.videosink.expose()
        return False


    def set_xwindow_id(self):
        """ set the widget's XID on the configured videosink. """
        if not self.videosink:
            return
        if self.have_set_xid:
            return
        
        if self.window:
            if platform.system() == 'Windows':
                xid = self.window.handle
            else:
                xid = self.window.xid
            
            self.videosink.set_xwindow_id(xid)
            self.have_set_xid = True
            self.videosink.expose()


PlayerViewClass = plugin_registry.get_component_class('base:player_view')

class GtkPlayerView(PlayerViewClass):
    """
    This class implements gtk list view support
    """
    supported_controllers = ('base:player_controller',)

    def __init__(self):
        PlayerViewClass.__init__(self)
        self.context_path = 'gtk:gtk_context'

        self.vbox = gtk.VBox()
        self.videopanel = ViewerWidget()
        self.videopanel.set_size_request(200, 200)
        self.hbox = gtk.HBox()
        self.vbox.pack_start(self.videopanel, expand=False)
        self.vbox.pack_end(self.hbox, expand=False)

        translator = common.application.translator
        label = translator.translateTranslatable(T_(N_("no media")))
        self.uri_widget = gtk.Label(label)

        self.state_widget = gtk.combo_box_new_text()
        for state in player.STATES[1:4]:
            self.state_widget.append_text(str(state))
        self.state_widget.connect("changed", self._gtk_state_changed)

        self.hbox.pack_start(self.uri_widget)

        if platform.system() == 'Windows':
            vsink = 'directdrawsink'
        else:
            vsink = 'ximagesink'
        
        self._video_sink = gst.element_factory_make(vsink)
        self.player.video_sink = self._video_sink
        self.videopanel.videosink = self._video_sink

        self.context_handle = self.vbox


    def _init_xwindow_id(self):
        self.videopanel.have_set_xid = False
        self.videopanel.can_set_xid = True
        self.videopanel.set_xwindow_id()

    def _gtk_state_changed(self, widget):
        # FIXME: may be redirected to the controller instead
        new_state = widget.get_active_text()
        next_state = None

        if new_state == str(player.STATES.PLAYING):
            next_state  = player.STATES.PLAYING
        elif new_state == str(player.STATES.PAUSED):
            next_state = player.STATES.PAUSED
        elif new_state == str(player.STATES.STOPPED):
            next_state = player.STATES.STOPPED

        if not next_state:
            return

        old_state = self.player.state
        if old_state != next_state:
            self.controller.model.state = next_state


    def attribute_set(self, origin, key, old_value, new_value):
        PlayerViewClass.attribute_set(self, origin, key, old_value, new_value)
        if key == 'state':
            if new_value == player.STATES.PLAYING:
                self._play()
            elif new_value == player.STATES.PAUSED:
                self._pause()
            elif new_value == player.STATES.STOPPED:
                self._stop()
        if key == 'uri':
            self.player.uri = new_value
            label = new_value.label
            if isinstance(label, Translatable):
                translator = common.application.translator
                label = translator.translateTranslatable(label,
                                    self.frontend.languages)
            self.uri_widget.set_text(label)

            self._update_combo()

    def controller_changed(self, old_controller, new_controller):
        PlayerViewClass.controller_changed(self, old_controller, new_controller)

        if self.controller.uri != None:
            label = self.controller.uri.label
            if isinstance(label, Translatable):
                translator = common.application.translator
                label = translator.translateTranslatable(label,
                                    self.frontend.languages)
            self.uri_widget.set_text(label)

            state = self.controller.state
            if state == player.STATES.PLAYING:
                self._play()
            elif state == player.STATES.PAUSED:
                self._pause()
            elif state == player.STATES.STOPPED:
                self._stop()

            self._update_combo()

    def focused_changed(self, new_value):
        pass


    def _update_combo(self):
        if self.state_widget not in self.hbox.get_children():
            self.state_widget.size = (100,10)
            self.hbox.pack_end(self.state_widget)
            self.state_widget.show()

    def _pause(self):
        self._update_combo()
        self._init_xwindow_id()
        self.state_widget.set_active(player.STATES.index(player.STATES.PAUSED)-1)

    def _stop(self):
        self._update_combo()
        self.state_widget.set_active(player.STATES.index(player.STATES.STOPPED)-1)

    def _play(self):
        self._update_combo()
        self._init_xwindow_id()
        self.state_widget.set_active(player.STATES.index(player.STATES.PLAYING)-1)
