# -*- coding: utf-8 -*-

# Copyright (C) 2010-2011
#   Drakmail < drakmail@gmail.com >
#   NomerUNO < uno.kms@gmail.com >
#   Platon Peacel☮ve <platonny@ngs.ru>
#   Elec.Lomy.RU <Elec.Lomy.RU@gmail.com>
#   ADcomp <david.madbox@gmail.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 of the License, 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, see <http://www.gnu.org/licenses/>.

import gtk
import cairo


def check_screen(widget):
    # To check if the display supports alpha channels, get the colormap
    screen = widget.get_screen()
    colormap = screen.get_rgba_colormap()
    if colormap is None:
        colormap = screen.get_rgb_colormap()
        # Now we have a colormap appropriate for the screen, use it
    widget.set_colormap(colormap)


class Window(gtk.Window):
    def __init__(self, window_type=gtk.WINDOW_TOPLEVEL):
        gtk.Window.__init__(self, window_type)
        self.set_decorated(False)
        self.set_skip_taskbar_hint(True)
        self.set_skip_pager_hint(True)
        self.stick()
        self.set_app_paintable(True)
        self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
                        gtk.gdk.ENTER_NOTIFY |
                        gtk.gdk.LEAVE_NOTIFY)
        self.set_border_width(0)


class PopupWindow(Window):
    def __init__(self, bg_color, border_color, border=6):
        Window.__init__(self, gtk.WINDOW_TOPLEVEL)
        self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_UTILITY)
        self.focus_check = False
        self.add_events(gtk.gdk.FOCUS_CHANGE_MASK)
        self.connect('expose-event', self.expose)
        self.connect('size-allocate', self.win_size_allocate)
        self.bg_surface = None

        check_screen(self)
        self.set_border_width(int(border / 2) + 1)

        self.border = border
        self.bg_color = bg_color
        self.border_color = border_color

        self.width = 0
        self.height = 0

    def win_size_allocate(self, widget, allocation):
        x, y, width, height = allocation

        if self.width == width and self.height == height:
            return

        self.bg_surface = cairo.ImageSurface(
                cairo.FORMAT_ARGB32, width, height)

        if not self.is_composited() and self.border > 0:
            bitmap = gtk.gdk.Pixmap(None, width, height, 1)
            cr = bitmap.cairo_create()
            # Clear the bitmap to False
            cr.set_source_rgb(0, 0, 0)
            cr.set_operator(cairo.OPERATOR_DEST_OUT)
            cr.paint()
            # Draw our shape into the bitmap using cairo
            cr.set_operator(cairo.OPERATOR_OVER)
            self.draw_shape(cr, x + 1, y + 1, width - 2, height - 2)
            self.shape_combine_mask(bitmap, 0, 0)

        cr = cairo.Context(self.bg_surface)
        ## Full transparent
        cr.set_source_rgba(0, 0, 0, 0)
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.paint()
        ## Draw next over 'transparent window'
        cr.set_operator(cairo.OPERATOR_OVER)
        self.draw_shape(cr, x + 1, y + 1, width - 2, height - 2)

        self.width, self.height = width, height

    def expose(self, widget, event):
        # On X11 this function returns whether a compositing
        # manager is running for the widget's screen
        if self.is_composited:
            cr = widget.window.cairo_create()
            ## Full transparent window
            cr.set_source_rgba(0, 0, 0, 0)
            cr.set_operator(cairo.OPERATOR_SOURCE)
            cr.paint()
            ## paint background
            cr.set_source_surface(self.bg_surface, 0, 0)
            cr.paint()

    def draw_shape(self, cr, x, y, width, height, flag=False):
        r, g, b = self.bg_color
        opacity = 0.92
        #~ opacity = self.bar.opacity

        cr.translate(x, y)

        lg = cairo.LinearGradient(0, y, 0, y + height)
        i = 0.0
        while i <= 0.3:
            lg.add_color_stop_rgba(1 - i,
                    r - (i * r),
                    g - (i * g),
                    b - (i * b),
                    opacity)
            i += 0.1
        i = 0.7
        while i <= 1.0:
            lg.add_color_stop_rgba(1 - i,
                                   r - (1 - i) * r,
                                   g - (1 - i) * g,
                                   b - (1 - i) * b,
                                   opacity)
            i += 0.1

        radius = min(self.border, width / 2, height / 2)

        cr.move_to(0, radius)
        cr.arc(radius, radius, radius, 3.14, 1.5 * 3.14)
        cr.line_to(width - radius, 0)
        cr.arc(width - radius, 0 + radius, radius, 1.5 * 3.14, 0.0)
        cr.line_to(width, height - radius)
        cr.arc(width - radius, height - radius, radius, 0.0, 0.5 * 3.14)
        cr.line_to(radius, height)
        cr.arc(radius, height - radius, radius, 0.5 * 3.14, 3.14)
        cr.close_path()
        cr.set_source(lg)
        cr.fill()

        cr.save()
        #~ cr.translate(x, y)

        cr.move_to(0, radius)
        cr.arc(radius, radius, radius, 3.14, 1.5 * 3.14)
        cr.line_to(width - radius, 0)
        cr.arc(width - radius, 0 + radius, radius, 1.5 * 3.14, 0.0)
        cr.line_to(width, height - radius)
        cr.arc(width - radius, height - radius, radius, 0.0, 0.5 * 3.14)
        cr.line_to(radius, height)
        cr.arc(radius, height - radius, radius, 0.5 * 3.14, 3.14)
        cr.close_path()

        r, g, b = self.border_color
        cr.set_source_rgba(r, g, b, opacity)
        cr.set_line_width(2)
        cr.stroke()
        cr.restore()

        return False
