# -*- coding: utf-8 -*-
"""
PKMeter Charts
"""
import time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from pkm import pkmixins, utils
from pkm.decorators import threaded_method


class PKLineChart(QtWidgets.QFrame, pkmixins.LayoutMixin):

    def __init__(self, etree, control, parent=None):
        QtWidgets.QFrame.__init__(self)
        self.autoscale = True                           # Autoscale max value
        self.bgcolor = QtGui.QColor(255,255,255,10)     # Chart background color
        self.colors = [QtGui.QColor(255,0,0)]           # Chart line colors
        self.interval = None                            # Set update sec for smooth scrolling
        self.maxvalue = 1                               # Max value in dataset
        self.minmax = 1                                 # Minimum max value
        self.pxperpt = 3                                # Pixels per point
        self.showzero = True                            # Plot zero values
        self.data = []
        self.numpoints = None
        self.offset = 0
        pkmixins.LayoutMixin._init(self, etree, control, parent)

    def _init_data(self, values, numpoints):
        self.data = []
        self.numpoints = numpoints
        for i in range(self.numpoints):
            self.data.append([-1] * len(values))

    def attribute_bgcolor(self, value):
        self.bgcolor = utils.hex_to_qcolor(value)

    def attribute_autoscale(self, value):
        self.autoscale = True if value.lower() == 'true' else False

    def attribute_colors(self, value):
        self.colors = [utils.hex_to_qcolor(v) for v in value.split(',')]

    def attribute_interval(self, value):
        self.interval = int(float(value))

    def attribute_minmax(self, value):
        self.minmax = float(value)

    def attribute_pxperpt(self, value):
        self.pxperpt = int(value)

    def attribute_showzero(self, value):
        self.showzero = True if value.lower() == 'true' else False

    @threaded_method
    def attribute_values(self, values):
        if not values: return None
        values = [float(v) for v in values.split(',')]
        self.showit = False
        if len(values) == 2:
            self.showit = True
        numpoints = int(self.width() / self.pxperpt)
        if not self.data or numpoints != self.numpoints:
            self._init_data(values, numpoints)
        self.data = self.data[1:] + [values]
        if self.autoscale:
            self.maxvalue = max([max(x) for x in self.data] + [self.minmax])
            self.setToolTip('Max: %s' % self.maxvalue)
        if self.interval:
            loops = self.interval * 10
            for i in range(loops):
                self.offset = self.pxperpt * (i / float(loops))
                self.update()
                time.sleep(self.interval / float(loops))
        else:
            self.update()

    def paintEvent(self, event):
        if not self.data: return
        QtWidgets.QFrame.paintEvent(self, event)
        painter = QtGui.QPainter()
        painter.begin(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        # Draw background
        painter.setBrush(QtGui.QBrush(self.bgcolor))
        painter.setPen(Qt.NoPen)
        painter.drawRoundedRect(self.contentsRect(), 2, 2)
        # Draw the Lines
        for i in range(len(self.data[0])):
            path = None
            pen = QtGui.QPen(self.colors[i % len(self.colors)])
            for j in range(len(self.data)):
                value = self.data[j][i]
                prevvalue = self.data[j-1][i]
                if value == -1 or prevvalue == -1:
                    continue
                if not self.showzero and value <= 0 and prevvalue <= 0:
                    continue
                x1 = (self.pxperpt * (j - 0.5) + self.pxperpt / 4) - self.offset
                x2 = (self.pxperpt * j + self.pxperpt / 4) - self.offset
                y1 = self.height() - int((self.height() - 1) * (prevvalue / self.maxvalue))
                y2 = self.height() - int((self.height() - 1) * (value / self.maxvalue))
                path = path or QtGui.QPainterPath(QtCore.QPointF(x1,y1))
                path.cubicTo(x1, y1, x1, y2, x2, y2)
            if path:
                painter.strokePath(path, pen)
        painter.end()


class PKPieChart(QtWidgets.QFrame, pkmixins.LayoutMixin):

    def __init__(self, etree, control, parent=None):
        QtWidgets.QFrame.__init__(self)
        self.bgcolor = QtGui.QColor(255,255,255,13)     # Chart background color
        self.colors = [QtGui.QColor(255,0,0)]           # Chart line colors
        self.data = []                                  # Current plot data
        pkmixins.LayoutMixin._init(self, etree, control, parent)

    def attribute_bgcolor(self, value):
        self.bgcolor = utils.hex_to_qcolor(value)

    def attribute_colors(self, value):
        self.colors = [utils.hex_to_qcolor(v) for v in value.split(',')]

    def attribute_values(self, values):
        if not values: return None
        self.data = [float(v) for v in values.split(',')]
        self.update()

    def paintEvent(self, event):
        QtWidgets.QFrame.paintEvent(self, event)
        painter = QtGui.QPainter()
        painter.begin(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setPen(Qt.NoPen)
        # Draw the Pie
        rwidth = int(min([self.width(), self.height()]) - 2)
        x = int((self.width() / 2) - (rwidth / 2))
        y = int((self.height() / 2) - (rwidth / 2))
        rect = QtCore.QRect(x, y, rwidth, rwidth)
        angle1 = 0
        for i in range(len(self.data)):
            angle2 = angle1 + (3.6 * self.data[i])
            painter.setBrush(QtGui.QBrush(self.colors[i % len(self.colors)]))
            painter.drawPie(rect, angle1*-16, (angle2-angle1)*-16)
            angle1 = angle2
        # Draw the remainer (background)
        angle2 = 360
        painter.setBrush(QtGui.QBrush(self.bgcolor))
        painter.drawPie(rect, angle1*-16, (angle2-angle1)*-16)
        painter.end()


class PKVBarChart(QtWidgets.QFrame, pkmixins.LayoutMixin):

    def __init__(self, etree, control, parent=None):
        QtWidgets.QFrame.__init__(self)
        self.bgcolor = QtGui.QColor(255,255,255,10)     # Chart background color
        self.colors = [QtGui.QColor(255,0,0)]           # Chart line colors
        self.data = []                                  # Current plot data
        pkmixins.LayoutMixin._init(self, etree, control, parent)

    def attribute_bgcolor(self, value):
        self.bgcolor = utils.hex_to_qcolor(value)

    def attribute_colors(self, value):
        self.colors = [utils.hex_to_qcolor(v) for v in value.split(',')]

    def attribute_values(self, values):
        if not values: return None
        self.data = [float(v) for v in values.split(',')]
        self.update()

    def paintEvent(self, event):
        if not self.data: return
        QtWidgets.QFrame.paintEvent(self, event)
        painter = QtGui.QPainter()
        painter.begin(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        # Draw background
        painter.setBrush(QtGui.QBrush(self.bgcolor))
        painter.setPen(Qt.NoPen)
        painter.drawRoundedRect(self.contentsRect(), 2, 2)
        # Draw the bars
        barwidth = (self.width() - 4) / len(self.data)
        for i in range(len(self.data)):
            barheight = int(self.height() * (self.data[i] / 100))
            baroffset = i * barwidth + 2
            painter.setBrush(QtGui.QBrush(self.colors[i % len(self.colors)]))
            painter.drawRoundedRect(baroffset, self.height()-barheight, barwidth, barheight, 1, 1)
        painter.end()