# -*- 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.

import gobject
import pgm
from pgm.timing import implicit
from pgm.graph.group import Group
from pgm.graph.text import Text
from pgm.graph.image import Image
from pgm.utils import image as image_utils

from pgm.widgets import const

NONE_FOCUSED=-1
BACK_FOCUSED=0
ZOOM_OUT_FOCUSED=1
ZOOM_IN_FOCUSED=2

class GridBar(Group):
    attr_focus_map = {BACK_FOCUSED: 'back',
                      ZOOM_IN_FOCUSED: 'zoom_in',
                      ZOOM_OUT_FOCUSED: 'zoom_out'}


    __gsignals__ = { 
        'focus-changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                           (gobject.TYPE_INT,))
        }


    def __init__(self, canvas=None, layer=pgm.DRAWABLE_MIDDLE,
                 width=1.0, height=2.0,
                 background=None, main_text="", sub_text="",
                 back_button=None, back_button_focused=None,
                 zoom_in_button=None, zoom_in_button_focused=None,
                 zoom_out_button=None, zoom_out_button_focused=None):
        
        super(GridBar, self).__init__(canvas=canvas, layer=layer)
        self._focused_button = NONE_FOCUSED
        
        self._setup_initial_widgets()

        self.background = background
        self.main_text = main_text
        self.sub_text = sub_text
        
        self.back_button = back_button
        self.back_button_focused = back_button_focused
     
        self.zoom_in_button = zoom_in_button
        self.zoom_in_button_focused = zoom_in_button_focused

        self.zoom_out_button = zoom_out_button
        self.zoom_out_button_focused = zoom_out_button_focused

    def canvas__set(self, canvas):
        super(GridBar, self).canvas__set(canvas)
        self._layout()

    def _setup_initial_widgets(self):
        self._main_text = self._create_text()
        self._sub_text = self._create_text()
        self.add(self._main_text)
        self.add(self._sub_text)

        unfocused_button_attrs = {'_back_img': 'back',
                                  '_zoom_in_img': 'zoom_in',
                                  '_zoom_out_img': 'zoom_out'}
        for attr in ['_background_img',
                     '_back_focused_img',
                     '_zoom_in_focused_img',
                     '_zoom_out_focused_img'] + unfocused_button_attrs.keys():
            img = Image()
            img.set_name(attr)
            img.bg_color = (0, 0, 0, 0)
            img.layout = pgm.IMAGE_FILLED
            setattr(self, attr, img)
            self.add(img)

        for attr, zone_name in unfocused_button_attrs.iteritems():
            mouse_zone = self._create_click_zone()
            mouse_zone.set_name(zone_name)
            
            img = getattr(self, attr)
            img_zone_name = '%s_zone' % img.get_name()
            setattr(self, img_zone_name, mouse_zone)
            self.add(mouse_zone)
            
    def _create_text(self):
        txt = Text()
        txt.font_family = "Nimbus Sans L Bold"
        txt.bg_color = (0, 0, 0, 0)
        txt.alignment = pgm.TEXT_ALIGN_CENTER
        txt.ellipsize = pgm.TEXT_ELLIPSIZE_MIDDLE
        txt.opacity = 255
        txt.visible = True
        return txt

    def _create_click_zone(self):
        mouse_zone = Image()
        mouse_zone.bg_color = (0, 0, 0, 0)
        mouse_zone.visible = True
        mouse_zone.connect("clicked", self._img_clicked)
        return mouse_zone

    def _layout(self):
        self._focus_buttons()
        canvas = self.canvas
        if canvas:
            self._layout_buttons()
            
            # text are in front of buttons and background
            # FIXME: ideally there would be an horizontal scrolling animation
            #        if any text overlaps the buttons
            z = self.z + 2

            self._background_img.size = self.size

            text_x = self._back_img.x + self._back_img.width * 0.95
            w = canvas.width - text_x - self._zoom_in_img.width - self._zoom_out_img.width
            
            if w > 0:
                self._main_text.width = w
                
            self._main_text.font_height = 0.5
            self._main_text.position = (text_x, 0.01, z)

            self._sub_text.width = canvas.width
            self._sub_text.font_height = 0.5
            self._sub_text.fg_color = (150, 150, 150, 255)
            self._sub_text.position = (0, canvas.height / 20., z)

    def _layout_buttons(self):
        z = self.z + 1
        
        canvas = self.canvas
        
        y = canvas.height / 150.
        button_height = canvas.height / 20.
        zoom_in_x = canvas.width * 0.91

        self._back_img.height = button_height 
        self._back_focused_img.height = button_height
        self._zoom_in_img.height = button_height
        self._zoom_in_focused_img.height = button_height
        self._zoom_out_img.height = button_height
        self._zoom_out_focused_img.height = button_height

        get_width = image_utils.get_width_from_par

        self._back_img.width = get_width(self._back_img)
        self._back_focused_img.width = get_width(self._back_focused_img)
        self._back_img_zone.size = self._back_img.size

        self._zoom_in_img.width = get_width(self._zoom_in_img)
        self._zoom_in_focused_img.width = get_width(self._zoom_in_focused_img)
        self._zoom_in_img_zone.size = self._zoom_in_img.size

        self._zoom_out_img.width = get_width(self._zoom_out_img)
        self._zoom_out_focused_img.width = get_width(self._zoom_out_focused_img)
        self._zoom_out_img_zone.size = self._zoom_out_img.size
        
        zoom_in_x = canvas.width - (get_width(self._zoom_in_img))

        back_position = (0, y, z)
        zoom_in_position = (zoom_in_x, y, z)
        zoom_out_position = (zoom_in_position[0] - self._zoom_out_img.width,
                             y, z)
        
        self._back_img.position = back_position
        self._back_focused_img.position = back_position
        self._back_img_zone.position = back_position

        self._zoom_in_img.position = zoom_in_position
        self._zoom_in_focused_img.position = zoom_in_position
        self._zoom_in_img_zone.position = zoom_in_position
        
        self._zoom_out_img.position = zoom_out_position
        self._zoom_out_focused_img.position = zoom_out_position
        self._zoom_out_img_zone.position = zoom_out_position

    def _unfocus(self, attr):
        name = '_%s_img' % attr
        focused_name = '_%s_focused_img' % attr
        getattr(self, name).visible = True
        getattr(self, focused_name).visible = False

    def _focus(self, attr):
        name = '_%s_img' % attr
        focused_name = '_%s_focused_img' % attr
        getattr(self, name).visible = False
        getattr(self, focused_name).visible = True
        
    def _focus_buttons(self, emit_signal=False):
        focused = self._focused_button

        if focused == NONE_FOCUSED:
            self._unfocus('back')
            self._unfocus('zoom_in')
            self._unfocus('zoom_out')
        else:
            to_focus = self.attr_focus_map.get(focused)
            
            self._focus(to_focus)
            if emit_signal:
                self.emit('focus-changed', focused)
                
            for attr in self.attr_focus_map.values():
                if attr != to_focus:
                    self._unfocus(attr)
            
    def _set_image(self, img, image_file, visible=True):
        if img is not None:
            img.clear()
        if image_file is not None:
            img.visible = visible
            img.connect("pixbuf-loaded", self._img_loaded)
            img.set_from_file(image_file)
            
    def _img_loaded(self, img):
        if img not in self.children:
            self.add(img)
        self._layout()
    
    def _img_clicked(self, mouse_zone, x, y, z, time, button_type):
        img_name = mouse_zone.get_name()
        for const, name in self.attr_focus_map.iteritems():
            if name == img_name:
                self._focused_button = const
                break
        self._focus_buttons(emit_signal=True)
        
        # Stop propagation of the signal
        return True
    
    def focused_button__set(self, value):
        self._focused_button = value
        self._focus_buttons()

    def focused_button__get(self):
        return self._focused_button
        
    def background__set(self, image_file):
        self._background_img.interp = pgm.IMAGE_NEAREST
        self._set_image(self._background_img, image_file)

    def background__get(self):
        return self._background_img

    def main_text__set(self, text):
        self._main_text.label = text
        self._layout()
        
    def main_text__get(self):
        return self._main_text

    def sub_text__set(self, text):
        self._sub_text.label = text
        self._layout()

    def sub_text__get(self):
        return self._sub_text

    def back_button__set(self, image_file):
        self._set_image(self._back_img, image_file)
        
    def back_button__get(self):
        return self._back_img
    
    def back_button_focused__set(self, image_file):
        self._set_image(self._back_focused_img, image_file, visible=False)

    def back_button_focused__get(self):
        return self._back_focused_img

    def zoom_in_button__set(self, image_file):
        self._set_image(self._zoom_in_img, image_file)

    def zoom_in_button__get(self):
        return self._zoom_in_img
    
    def zoom_in_button_focused__set(self, image_file):
        self._set_image(self._zoom_in_focused_img, image_file, visible=False)

    def zoom_in_button_focused__get(self):
        return self._zoom_in_focused_img

    def zoom_out_button__set(self, image_file):
        self._set_image(self._zoom_out_img, image_file)
        
    def zoom_out_button__get(self):
        return self._zoom_out_img
    
    def zoom_out_button_focused__set(self, image_file):
        self._set_image(self._zoom_out_focused_img, image_file, visible=False)
        
    def zoom_out_button_focused__get(self):
        return self._zoom_out_focused_img

if __name__ == "__main__":
    import pgm
    from pgm.widgets.grid_ng import Grid
    #from pgm.widgets.list_ng import List as Grid
    from pgm.graph.group import Group

    def on_key_press(viewport, event, widget):
        # quit on q or ESC
        if event.keyval == pgm.keysyms.q or \
           event.keyval == pgm.keysyms.Escape:
            pgm.main_quit()
            
        elif event.keyval == pgm.keysyms.a:
            canvas = viewport.get_canvas()
            canvas.regenerate()
            
        elif event.keyval == pgm.keysyms.f:
            viewport.fullscreen = not viewport.fullscreen
            
        elif event.keyval == pgm.keysyms.Right:
            new_value = widget.focused_button + 1
            if new_value < ZOOM_IN_FOCUSED + 1:
                widget.focused_button = new_value

        elif event.keyval == pgm.keysyms.Left:
            new_value = widget.focused_button - 1
            if new_value >= NONE_FOCUSED:
                widget.focused_button = new_value

    def on_delete(viewport, event):
        pgm.main_quit()

    # OpenGL viewport creation
    factory = pgm.ViewportFactory('opengl')
    gl = factory.create()
    gl.title = 'GridBar widget'

    # Canvas and image drawable creation
    canvas = pgm.Canvas()

    # Bind the canvas to the OpenGL viewport
    gl.set_canvas(canvas)
    gl.show()

##     grp = Group()
##     grp.visible = True
##     grp.canvas = canvas

##     list_widget = Grid()
##     list_widget.orientation = const.HORIZONTAL
##     list_widget.width = 3.0
##     list_widget.height = 2.0
##     list_widget.visible_range_size = 5
##     list_widget.visible = True
##     list_widget.canvas = canvas
##     #grp.add(list_widget)
##     list_widget.position = (0.5, 0.5, 0.0)

    bar_height = 0.35
    bar_y = canvas.height - bar_height
    #bar_x = -0.5
    bar_x = 0.
    
    bar = GridBar()
    bar.visible = True

    bar.canvas = canvas
    #grp.add(bar)
    #list_widget.add(bar)
    bar.position = (bar_x, bar_y, 0.0)
    bar.size = (canvas.width, bar_height)
    
    bar.background = 'theme/bottom-grid-bar.png'
    bar.zoom_in_button = 'theme/grid-morebutton.png'
    bar.zoom_out_button = 'theme/grid-lessbutton.png'
    bar.back_button = 'theme/grid-backbutton.png'
    
    bar.zoom_in_button_focused = 'theme/grid-morebutton-focused.png'
    bar.zoom_out_button_focused = 'theme/grid-lessbutton-focused.png'
    bar.back_button_focused = 'theme/grid-backbutton-focused.png'


    bar.main_text = "Quelqu'un m'a dit que tu m'aimes encore"
    bar.sub_text = 'Carla Bruni'
    
    # Let's start a mainloop
    gl.connect('key-press-event', on_key_press, bar)
    gl.connect('delete-event', on_delete)
    pgm.main()
