# -*- coding: utf-8 -*-
# qt.glal.py
"""This module provides a graphic library abstraction layer for Cyclograph"""

# Copyright (C) 2008-2014 Federico Brega, Pierluigi Villani

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



from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtPrintSupport import QPrinter
from PyQt5 import QtCore
from version import VERSION

from . import gui


def initapp(*args):
    """Create initial app for gui"""
    app = QApplication(*args)
    
    # Tell to the graphic library witch language use
    translations_path = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath)
    translation_file = "qt_" + str(QtCore.QLocale.system().name())
    translator = QtCore.QTranslator(app)
    translator.load(translation_file, translations_path)
    app.installTranslator(translator)
    
    #Enable support for High resolution disaplays
    app.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
    
    return app


def bind(cgfunc, menuopt):
    """Connect gui menu option with cg function"""
    return menuopt.triggered.connect(cgfunc)


def bind_close(cg_exit, gui):
    """Connect gui close event with cg exit function"""
    gui.cg_exit = cg_exit
    return gui.menu_item_exit.triggered.connect(gui.quit)


def ToolbarBind(fun, button):
    """Connect gui toolbar button with cg function"""
    return button.triggered.connect(fun)


def OptionCheck(guiopt, option):
    """Set a gui menu option to selected/unselected """
    guiopt.setChecked(option)


def enable_saving(gui, bool_val):
    """Enable or disable saving options according to bool_val"""
    gui.menu_item_save.setEnabled(bool_val)
    gui.menu_item_save_as.setEnabled(bool_val)
    gui.action_add.setEnabled(bool_val)
    gui.action_edit.setEnabled(bool_val)
    gui.action_delete.setEnabled(bool_val)
    gui.action_plot.setEnabled(bool_val)
    gui.action_map.setEnabled(bool_val)
    gui.action_properties.setEnabled(bool_val)


def addstatusbartext(maingui, text):
    """Add text to main gui status bar"""
    maingui.addstatusbartext(text)


def signalbug(event=None):
    """Open webpage to signal bugs"""
    bugUrl = 'http://sourceforge.net/project/memberlist.php?group_id=227295'
    QDesktopServices.openUrl(QtCore.QUrl(bugUrl))

class Message(QtCore.QObject):
    """ Qt message"""
    
    sent = QtCore.pyqtSignal(str, int, int) #message name, slope_number, row_num
    
    def __init__(self):
        QtCore.QObject.__init__(self)
    
    def send(self, message, slope_number, row_num):
        """ Send message"""
        self.sent.emit(message, slope_number, row_num)
        
    @staticmethod
    def subscribe(function, emitter, message):
        """ Subscribe message"""
        def callback_check(message_sent, slope_number, row_num):
            if message_sent == message:
                function(slope_number, row_num)
        emitter.sent.connect(callback_check)


class Notebook:
    """ Qt Notebook"""
    def __init__(self, notebook, fun_close):
        self.notebook = notebook
        self.fun_close = fun_close
        self.notebook.setTabsClosable(True)
        self.notebook.tabCloseRequested[int].connect(fun_close)

    def Page(self):
        """ Return qt Page"""
        return gui.Page(self.notebook)

    def set_page_label(self, page_num, text):
        """ Set page label text"""
        self.notebook.setTabText(page_num,  text)

    def add_page(self, page, title):
        """ Add page"""
        self.notebook.addTab(page, title)
        page.button_close.setVisible(False)
        self.notebook.setCurrentWidget(page)

    def remove_page(self, page_num):
        """ Remove page"""
        self.notebook.removeTab(page_num)

    def getselpagnum(self):
        """ Return number from selected page"""
        return self.notebook.currentIndex()

    def setselpagnum(self, page_num):
        """Set current selected page"""
        self.notebook.setCurrentWidget(self.get_page(page_num))

    def get_page(self, page_num):
        """ Return page"""
        page = self.notebook.widget(page_num)
        return page

    def get_pagenum(self, argument):
        """Return page_num from page passed as argument"""
        return argument[0]


class DeviceContext():
    """Device Context Qt class wrapper"""
    def _convqcolor(self, color):
        """ Convert color"""
        if isinstance(color, str):
            if color.startswith("rgb"):
                col = list(map(int, color[4:-1].split(',')))
                return QColor(*col)
            else:
                return QColor(color)
        else:
            return QColor(*color)

    def init_draw_surf(self, panel):
        """ Initialize drawing surface"""
        (self.size_x, self.size_y) = (panel.width(), panel.height())
        self.paint = QPainter()
        self.paint.begin(panel)
        self.paint.setRenderHint(QPainter.SmoothPixmapTransform)
        self.paint.setRenderHint(QPainter.Antialiasing)

    def shear(self, shear):
        """ device shear"""
        self.paint.shear(0.0, shear)

    def getsize(self):
        """ Return size"""
        return (self.size_x, self.size_y)

    def gradfill(self, rect, startcolor, endcolor):
        """ Fill gradient"""
        (sx, sy, ex, ey) = (rect[0], rect[1], rect[0], rect[1]+rect[3])
        gradient = QLinearGradient(sx, sy, ex, ey)
        sqcol = self._convqcolor(startcolor)
        gradient.setColorAt(0, sqcol)
        eqcol = self._convqcolor(endcolor)
        gradient.setColorAt(1, eqcol)
        brush = QBrush(gradient)
        self.paint.fillRect(QtCore.QRect(*rect), brush)

    def setpen(self, color, size):
        """ Set pen's color and size"""
        qcol = self._convqcolor(color)
        pen = QPen(qcol)
        pen.setWidth(size)
        self.paint.setPen(pen)

    def setfont(self, fontdict):
        """ Set font to use"""
        font = QFont()
        self.fontmetrics = QFontMetrics(font)
        try:
            font.setFamily(fontdict["des"])
            font.setPointSize(fontdict["dim"])
            font.setWeight(eval('QFont.'+fontdict["typ"].capitalize()))
            self.paint.setFont(font)
        except Exception:
            pass

    def drawtext(self, text, pos_x, pos_y):
        """ Draw text at position x,y"""
        self.paint.drawText(pos_x, pos_y+10, text)

    def gettextwidth(self, text):
        """ Return text length"""
        return self.fontmetrics.width(text)

    def gettextheight(self, text):
        """ Return text height"""
        return self.fontmetrics.height()

    def drawline(self, pos_x0, pos_y0, pos_x1, pos_y1):
        """ Draw line"""
        self.paint.drawLine(pos_x0, pos_y0, pos_x1, pos_y1)

    def setlineargradientbrush(self, colorlist, startp, endp):
        """ Get a linear gradient from startp to endp, using colors in colorlist.
        The elments of colorlist are tuple in the format (color, realtive position)."""
        grad = QLinearGradient(startp[0], startp[1], endp[0], endp[1])
        for color in colorlist:
            grad.setColorAt(color[1], self._convqcolor(color[0]))
        brush = QBrush(grad)
        self.paint.setBrush(brush)

    def setbrush(self, color):
        """ Set brush's color"""
        qcol = self._convqcolor(color)
        brush = QBrush(qcol)
        self.paint.setBrush(brush)

    def drawrectangle(self, pos_x0, pos_y0, width, height):
        """ Draw rectangle"""
        self.paint.drawRect(pos_x0, pos_y0, width, height)

    def drawrotatedtext(self, text, pos_x, pos_y, angle):
        """ Draw rotated text at position x,y by angle"""
        self.paint.save()
        self.paint.rotate(-angle)
        transform = QTransform()
        transform.rotate(angle)
        (newx, newy) = transform.map(pos_x+10, pos_y-5)
        self.paint.drawText(newx, newy, text)
        self.paint.restore()

    def drawpolygon(self, sequence):
        """ Draw polygon"""
        points = [QtCore.QPoint(*p) for p in sequence]
        self.paint.drawPolygon(*points)

    def startpath(self, point):
        """ Start a path in the specified point,"""
        point = QtCore.QPointF(*point)
        path = QPainterPath()
        path.moveTo(point)
        return path

    def drawpathlineto(self, path, point):
        """ Draw a straight line from the last point to the given point."""
        point = QtCore.QPointF(*point)
        path.lineTo(point)

    def drawpathcubicto(self, path, controlpoints):
        """ Draw a cubic Beziér frome the last point using the given list of
        three control points."""
        points = [QtCore.QPointF(pnt[0], pnt[1]) for pnt in controlpoints]
        path.cubicTo(*points)

    def endpath(self, path):
        """ Show the path."""
        self.paint.drawPath(path)

    def end_draw(self):
        """ Finish drawing"""
        self.paint.end()
        del self.paint


class Image():
    """Image Qt class wrapper"""
    def __init__(self, size_x,  size_y, plotfnct):
        (self.size_x, self.size_y) = (size_x, size_y)
        self.plotfnct = plotfnct
        self.image = QPixmap(size_x, size_y)
        self.image.fill()  # white backgound

    def plot(self, settings):
        """ Draw slope to the device context"""
        dcwrpp = DeviceContext()
        (dcwrpp.size_x, dcwrpp.size_y) = (self.size_x, self.size_y)
        dcwrpp.paint = QPainter()
        dcwrpp.paint.begin(self.image)
        dcwrpp.paint.setRenderHint(QPainter.SmoothPixmapTransform)
        dcwrpp.paint.setRenderHint(QPainter.Antialiasing)
        self.plotfnct(settings, dcwrpp)
        dcwrpp.end_draw()

    def savetofile(self, path, format):
        """ Save image to file"""
        self.image.save(path, format)


class Pdf():
    """Qt pdf class wrapper"""
    def __init__(self, filepath):
        self.dy = 90
        self.dx = 300
        self.y_incr = 30
        self.printer = QPrinter(QPrinter.ScreenResolution)
        self.printer.setOutputFormat(QPrinter.PdfFormat)
        self.printer.setOutputFileName(filepath)
        self.printer.setFullPage(True)
#        paperSize = QtCore.QSizeF(793, 1122)
#        self.printer.setPaperSize(paperSize, QPrinter.Millimeter)
        self.printer.setCreator('Cyclograph {0}'.format(VERSION))
        self.painter = QPainter()
        self.painter.begin(self.printer)
        self.painter.setRenderHint(QPainter.SmoothPixmapTransform)
        self.painter.setRenderHint(QPainter.Antialiasing)
        self.painter.setFont(QFont('Decorative', 18))

    def plot_image(self, settings, size_x, size_y, plotfnct):
        """ Draw slope to pdf"""
        image = QPicture()
        dcwrpp = DeviceContext()
        (dcwrpp.size_x, dcwrpp.size_y) = (size_x, size_y)
        dcwrpp.paint = QPainter()
        dcwrpp.paint.begin(image)
        dcwrpp.paint.setRenderHint(QPainter.SmoothPixmapTransform)
        dcwrpp.paint.setRenderHint(QPainter.Antialiasing)
        plotfnct(settings, dcwrpp)
        dcwrpp.end_draw()
        self.painter.drawPicture(0, 0, image)
        self.dy += size_y

    def addtext(self, text):
        self.dy += self.y_incr
        self.painter.setPen(QColor(0, 0, 0))
        self.painter.drawText(self.dx, self.dy, text)

    def addtitle(self, text):
        self.dy += self.y_incr
        self.painter.setPen(QColor(0, 0, 102))
        self.painter.drawText(self.dx-50, self.dy, text+":")

    def save(self):
        """Save pdf"""
        self.painter.end()


class ProgressDialog():
    """ Progress dialog for importkml"""
    def __init__(self):
        self.pd = QProgressDialog(_("Downloading altitudes"),
                                         _("Cancel"), 0, 1000)

    def update(self, value):
        """Update the progress shown and return if user want to abort."""
        self.pd.setValue(value)
        return self.pd.wasCanceled()

    def destroy(self):
        """ Destroy progress dialog"""
        self.pd = None


class Timer():
    """ Timer for Qt gui"""

    def __init__(self, period, callback):
        self.timer = self.timer = QtCore.QTimer()
        self.period = period
        self.timer.timeout.connect(callback)

    def start(self):
        """ Start timer count"""
        self.timer.start(self.period)

    def stop(self):
        """ Stop timer count"""
        self.timer.stop()

# vim:sw=4:softtabstop=4:expandtab
