import configparser
import math, re, os
import time
from functools import partial

from PyQt5 import QtGui, QtCore, QtWidgets

import pyqtgraph as pg
from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtGui import QRadialGradient, QColor
from PyQt5.QtWidgets import QLabel, QCheckBox
from scipy.optimize import leastsq
import scipy.optimize as optimize
import numpy as np

from utilities.templates import ui_category_row_2 as ui_category_row
from utilities.templates import ui_expt_row


colors = ['#00ff00', '#ff0000', '#ffff80', (10, 255, 255)] + [
    (50 + np.random.randint(200), 50 + np.random.randint(200), 150 + np.random.randint(100)) for a in range(10)]



class MyRow(QtWidgets.QFrame, ui_category_row.Ui_Form):
    set_output = None

    def __init__(self, title, description, imagepath, directory, clickEvent, parent=None):
        super(MyRow, self).__init__(parent)
        self.setupUi(self)
        self.title.setText(title)
        self.description.setText(description)
        # self.scene = QtWidgets.QGraphicsScene()
        # self.image.setScene(self.scene)
        self.directory = directory
        self.pic = QtGui.QPixmap(imagepath)
        self.scaled_pixmap = self.pic.scaled(self.image.size(), aspectRatioMode=1, transformMode=Qt.SmoothTransformation)
        self.image.setPixmap(self.scaled_pixmap)

        self.mousePressEvent = clickEvent


class MyExptRow(QtWidgets.QFrame, ui_expt_row.Ui_Form):
    set_output = None

    def __init__(self, title, description, imagepath, directory, clickEvent, parent=None):
        super(MyExptRow, self).__init__(parent)
        self.setupUi(self)
        self.title.setText(title)
        self.description.setText(description)
        # self.scene = QtWidgets.QGraphicsScene()
        # self.image.setScene(self.scene)
        self.directory = directory
        if(imagepath is not None and os.path.exists(imagepath)):
            self.pic = QtGui.QPixmap(imagepath)
            self.scaled_pixmap = self.pic.scaled(self.image.size(), aspectRatioMode=1,
                                                 transformMode=Qt.SmoothTransformation)
            self.image.setPixmap(self.scaled_pixmap)
        else:
            self.image.setParent(None)
            self.gridLayout_2.setColumnStretch(1, 0)

        self.mousePressEvent = clickEvent

class Gauge(QtWidgets.QWidget, QtWidgets.QGraphicsWidget):
    valueChanged = QtCore.pyqtSignal(float)

    def __init__(self, parent=None, name=''):
        super(Gauge, self).__init__(parent)
        self.decimals = True

        self.use_timer_event = False
        self.black = QtGui.QColor(0, 0, 0, 255)

        # self.valueColor = QtGui.QColor(50, 50, 50, 255)
        # self.set_valueColor(50, 50, 50, 255)
        # self.NeedleColor = QtGui.QColor(50, 50, 50, 255)
        self.set_NeedleColor(100, 100, 100, 255)
        self.NeedleColorReleased = self.NeedleColor
        # self.NeedleColorDrag = QtGui.QColor(255, 0, 00, 255)
        self.set_NeedleColorDrag(255, 0, 00, 255)

        self.set_ScaleValueColor(100, 100, 100, 255)
        self.set_DisplayValueColor(100, 100, 120, 255)
        self.set_DisplayTitleColor(200, 100, 120, 255)

        # self.CenterPointColor = QtGui.QColor(50, 50, 50, 255)
        self.set_CenterPointColor(50, 50, 50, 255)

        # self.valueColor = black
        # self.black = QtGui.QColor(0, 0, 0, 255)

        self.value_needle_count = 1
        self.value_needle = QtCore.QObject
        self.change_value_needle_style([QtGui.QPolygon([
            QtCore.QPoint(4, 4),
            QtCore.QPoint(-4, 4),
            QtCore.QPoint(-3, -120),
            QtCore.QPoint(0, -126),
            QtCore.QPoint(3, -120)
        ])])

        self.value_min = 0
        self.value_max = 1000
        self.value = self.value_min
        self.value_offset = 0
        self.value_needle_snapzone = 0.2
        self.last_value = 0

        # self.value2 = 0
        # self.value2Color = QtGui.QColor(0, 0, 0, 255)

        self.gauge_color_outer_radius_factor = 1
        self.gauge_color_inner_radius_factor = 0.9
        self.center_horizontal_value = 0
        self.center_vertical_value = 0
        self.debug1 = None
        self.debug2 = None
        self.scale_angle_start_value = 135
        self.scale_angle_size = 270
        self.angle_offset = 0

        # self.scala_main_count = 10
        self.set_scala_main_count(10)
        self.scala_subdiv_count = 5

        self.pen = QtGui.QPen(QtGui.QColor(0, 0, 0))
        self.font = QtGui.QFont('Decorative', 20)

        self.scale_polygon_colors = []
        self.set_scale_polygon_colors([
            [.00, QtGui.QColor("red")],
            [.1, QtGui.QColor("yellow")],
            [.15, QtGui.QColor("green")],
            [1, QtGui.QColor("transparent")]])

        # initialize Scale value text
        # self.enable_scale_text = True
        self.set_enable_ScaleText(True)
        self.scale_fontname = "Decorative"
        self.initial_scale_fontsize = 15
        self.scale_fontsize = self.initial_scale_fontsize

        # initialize Main value text
        self.enable_value_text = True
        self.value_fontname = "Decorative"
        self.initial_value_fontsize = 40
        self.value_fontsize = self.initial_value_fontsize
        self.text_radius_factor = 0.7

        # initialize Title text
        self.title_text = name
        self.enable_title_text = True
        self.title_fontname = "Serif"
        self.initial_title_fontsize = 32
        self.title_fontsize = self.initial_title_fontsize
        self.title_radius_factor = 0.2

        # En/disable scale / fill
        # self.enable_barGraph = True
        self.set_enable_barGraph(True)
        # self.enable_filled_Polygon = True
        self.set_enable_filled_Polygon(True)

        self.enable_CenterPoint = True
        self.enable_fine_scaled_marker = True
        self.enable_big_scaled_marker = True

        self.needle_scale_factor = 0.8
        self.enable_Needle_Polygon = True

        # necessary for resize
        self.setMouseTracking(False)

        self.update()
        self.rescale_method()

    def rescale_method(self):
        # print("slotMethod")
        if self.width() <= self.height():
            self.widget_diameter = self.width()
        else:
            self.widget_diameter = self.height()

        my_y = int(- self.widget_diameter / 2 * self.needle_scale_factor)
        self.change_value_needle_style([QtGui.QPolygon([
            QtCore.QPoint(4, 30),
            QtCore.QPoint(-4, 30),
            QtCore.QPoint(-2, my_y),
            QtCore.QPoint(0, my_y - 6),
            QtCore.QPoint(2, my_y)
        ])])

        self.scale_fontsize = self.initial_scale_fontsize * self.widget_diameter / 400
        self.value_fontsize = self.initial_value_fontsize * self.widget_diameter / 400

    def change_value_needle_style(self, design):
        # prepared for multiple needle instrument
        self.value_needle = []
        for i in design:
            self.value_needle.append(i)
        if not self.use_timer_event:
            self.update()

    def update_value(self, value, mouse_controlled=False):
        if (value == None): return
        if value <= self.value_min:
            self.value = self.value_min
        elif value >= self.value_max:
            self.value = self.value_max
        else:
            self.value = value
        if not mouse_controlled:
            self.valueChanged.emit(value)
        if not self.use_timer_event:
            self.update()

    def update_angle_offset(self, offset):
        self.angle_offset = offset
        if not self.use_timer_event:
            self.update()

    def center_horizontal(self, value):
        self.center_horizontal_value = value

    def center_vertical(self, value):
        self.center_vertical_value = value

    ###############################################################################################
    # Set Methods
    ###############################################################################################
    def set_NeedleColor(self, R=50, G=50, B=50, Transparency=255):
        # Red: R = 0 - 255
        # Green: G = 0 - 255
        # Blue: B = 0 - 255
        # Transparency = 0 - 255
        self.NeedleColor = QtGui.QColor(R, G, B, Transparency)
        self.NeedleColorReleased = self.NeedleColor

        if not self.use_timer_event:
            self.update()

    def set_NeedleColorDrag(self, R=50, G=50, B=50, Transparency=255):
        # Red: R = 0 - 255
        # Green: G = 0 - 255
        # Blue: B = 0 - 255
        # Transparency = 0 - 255
        self.NeedleColorDrag = QtGui.QColor(R, G, B, Transparency)

        if not self.use_timer_event:
            self.update()

    def set_ScaleValueColor(self, R=50, G=50, B=50, Transparency=255):
        # Red: R = 0 - 255
        # Green: G = 0 - 255
        # Blue: B = 0 - 255
        # Transparency = 0 - 255
        self.ScaleValueColor = QtGui.QColor(R, G, B, Transparency)

        if not self.use_timer_event:
            self.update()

    def set_DisplayValueColor(self, R=50, G=50, B=50, Transparency=255):
        self.DisplayValueColor = QtGui.QColor(R, G, B, Transparency)

        if not self.use_timer_event:
            self.update()

    def set_DisplayTitleColor(self, R=50, G=50, B=50, Transparency=255):
        self.DisplayTitleColor = QtGui.QColor(R, G, B, Transparency)

        if not self.use_timer_event:
            self.update()

    def set_CenterPointColor(self, R=50, G=50, B=50, Transparency=255):
        self.CenterPointColor = QtGui.QColor(R, G, B, Transparency)

        if not self.use_timer_event:
            self.update()

    def set_enable_Needle_Polygon(self, enable=True):
        self.enable_Needle_Polygon = enable

        if not self.use_timer_event:
            self.update()

    def set_enable_ScaleText(self, enable=True):
        self.enable_scale_text = enable

        if not self.use_timer_event:
            self.update()

    def set_enable_barGraph(self, enable=True):
        self.enable_barGraph = enable

        if not self.use_timer_event:
            self.update()

    def set_enable_value_text(self, enable=True):
        self.enable_value_text = enable

        if not self.use_timer_event:
            self.update()

    def set_enable_title_text(self, enable=True):
        self.enable_title_text = enable

        if not self.use_timer_event:
            self.update()

    def set_enable_CenterPoint(self, enable=True):
        self.enable_CenterPoint = enable

        if not self.use_timer_event:
            self.update()

    def set_enable_filled_Polygon(self, enable=True):
        self.enable_filled_Polygon = enable

        if not self.use_timer_event:
            self.update()

    def set_enable_big_scaled_grid(self, enable=True):
        self.enable_big_scaled_marker = enable

        if not self.use_timer_event:
            self.update()

    def set_enable_fine_scaled_marker(self, enable=True):
        self.enable_fine_scaled_marker = enable

        if not self.use_timer_event:
            self.update()

    def set_scala_main_count(self, count):
        if count < 1:
            count = 1
        self.scala_main_count = count

        if not self.use_timer_event:
            self.update()

    def set_MinValue(self, min):
        if self.value < min:
            self.value = min
        if min >= self.value_max:
            self.value_min = self.value_max - 1
        else:
            self.value_min = min

        if not self.use_timer_event:
            self.update()

    def set_MaxValue(self, max):
        if self.value > max:
            self.value = max
        if max <= self.value_min:
            self.value_max = self.value_min + 1
        else:
            self.value_max = max

        if not self.use_timer_event:
            self.update()

    def set_start_scale_angle(self, value):
        # Value range in DEG: 0 - 360
        self.scale_angle_start_value = value
        # print("startFill: " + str(self.scale_angle_start_value))

        if not self.use_timer_event:
            self.update()

    def set_total_scale_angle_size(self, value):
        self.scale_angle_size = value
        # print("stopFill: " + str(self.scale_angle_size))

        if not self.use_timer_event:
            self.update()

    def set_gauge_color_outer_radius_factor(self, value):
        self.gauge_color_outer_radius_factor = float(value) / 1000
        # print(self.gauge_color_outer_radius_factor)

        if not self.use_timer_event:
            self.update()

    def set_gauge_color_inner_radius_factor(self, value):
        self.gauge_color_inner_radius_factor = float(value) / 1000
        # print(self.gauge_color_inner_radius_factor)

        if not self.use_timer_event:
            self.update()

    def set_scale_polygon_colors(self, color_array):
        # print(type(color_array))
        if 'list' in str(type(color_array)):
            self.scale_polygon_colors = color_array
        elif color_array == None:
            self.scale_polygon_colors = [[.0, QtGui.QColor("transparent")]]
        else:
            self.scale_polygon_colors = [[.0, QtGui.QColor("transparent")]]

        if not self.use_timer_event:
            self.update()

    ###############################################################################################
    # Get Methods
    ###############################################################################################

    def get_value_max(self):
        return self.value_max

    ###############################################################################################
    # Painter
    ###############################################################################################

    def create_polygon_pie(self, outer_radius, inner_raduis, start, lenght):
        polygon_pie = QtGui.QPolygonF()
        # start = self.scale_angle_start_value
        # start = 0
        # lenght = self.scale_angle_size
        # lenght = 180
        # inner_raduis = self.width()/4
        # print(start)
        n = 360  # angle steps size for full circle
        # changing n value will causes drawing issues
        w = 360 / n  # angle per step
        # create outer circle line from "start"-angle to "start + lenght"-angle
        x = 0
        y = 0

        # todo enable/disable bar graf here
        if not self.enable_barGraph:
            # float_value = ((lenght / (self.value_max - self.value_min)) * (self.value - self.value_min))
            lenght = int(round((lenght / (self.value_max - self.value_min)) * (self.value - self.value_min)))
            # print("f: %s, l: %s" %(float_value, lenght))
            pass

        # mymax = 0

        for i in range(lenght + 1):  # add the points of polygon
            t = w * i + start - self.angle_offset
            x = outer_radius * math.cos(math.radians(t))
            y = outer_radius * math.sin(math.radians(t))
            polygon_pie.append(QtCore.QPointF(x, y))
        # create inner circle line from "start + lenght"-angle to "start"-angle
        for i in range(lenght + 1):  # add the points of polygon
            # print("2 " + str(i))
            t = w * (lenght - i) + start - self.angle_offset
            x = inner_raduis * math.cos(math.radians(t))
            y = inner_raduis * math.sin(math.radians(t))
            polygon_pie.append(QtCore.QPointF(x, y))

        # close outer line
        polygon_pie.append(QtCore.QPointF(x, y))
        return polygon_pie

    def draw_filled_polygon(self, outline_pen_with=0):
        if not self.scale_polygon_colors == None:
            painter_filled_polygon = QtGui.QPainter(self)
            painter_filled_polygon.setRenderHint(QtGui.QPainter.Antialiasing)
            painter_filled_polygon.translate(self.width() / 2, self.height() / 2)

            painter_filled_polygon.setPen(QtCore.Qt.NoPen)

            self.pen.setWidth(outline_pen_with)
            if outline_pen_with > 0:
                painter_filled_polygon.setPen(self.pen)

            colored_scale_polygon = self.create_polygon_pie(
                ((self.widget_diameter / 2) - (self.pen.width() / 2)) * self.gauge_color_outer_radius_factor,
                (((self.widget_diameter / 2) - (self.pen.width() / 2)) * self.gauge_color_inner_radius_factor),
                self.scale_angle_start_value, self.scale_angle_size)

            gauge_rect = QtCore.QRect(QtCore.QPoint(0, 0),
                                      QtCore.QSize(int(self.widget_diameter / 2 - 1), int(self.widget_diameter - 1)))
            grad = QtGui.QConicalGradient(QtCore.QPointF(0, 0), - self.scale_angle_size - self.scale_angle_start_value +
                                          self.angle_offset - 1)

            for eachcolor in self.scale_polygon_colors:
                grad.setColorAt(eachcolor[0], eachcolor[1])
            painter_filled_polygon.setBrush(grad)
            painter_filled_polygon.drawPolygon(colored_scale_polygon)
        # return painter_filled_polygon

    def draw_bg(self):
        diameter = self.widget_diameter
        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.translate(int(self.width() / 2), int(self.height() / 2))
        painter.setPen(QtCore.Qt.NoPen)

        # Create the radial gradient
        gradient = QRadialGradient(0, 0, self.widget_diameter / 2)
        gradient.setColorAt(0, QColor("#fff"))
        gradient.setColorAt(1, QColor("#acc"))

        # Set the gradient as the brush for the painter
        painter.setBrush(gradient)
        # painter.setBrush(QtGui.QColor("#dfe"))
        painter.drawEllipse(int(-diameter / 2), int(-diameter / 2), int(diameter), int(diameter))

    ###############################################################################################
    # Scale Marker
    ###############################################################################################

    def draw_big_scaled_markter(self):
        my_painter = QtGui.QPainter(self)
        my_painter.setRenderHint(QtGui.QPainter.Antialiasing)
        # Koordinatenursprung in die Mitte der Flaeche legen
        my_painter.translate(int(self.width() / 2), int(self.height() / 2))

        # my_painter.setPen(QtCore.Qt.NoPen)
        self.pen = QtGui.QPen(QtGui.QColor(0, 0, 0, 255))
        self.pen.setWidth(2)
        # # if outline_pen_with > 0:
        my_painter.setPen(self.pen)

        my_painter.rotate(self.scale_angle_start_value - self.angle_offset)
        steps_size = (float(self.scale_angle_size) / float(self.scala_main_count))
        scale_line_outer_start = self.widget_diameter / 2
        scale_line_lenght = (self.widget_diameter / 2) - (self.widget_diameter / 20)
        # print(stepszize)
        for i in range(self.scala_main_count + 1):
            my_painter.drawLine(int(scale_line_lenght), 0, int(scale_line_outer_start), 0)
            my_painter.rotate(steps_size)

    def create_scale_marker_values_text(self):
        painter = QtGui.QPainter(self)
        # painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)

        # Koordinatenursprung in die Mitte der Flaeche legen
        painter.translate(int(self.width() / 2), int(self.height() / 2))
        # painter.save()
        font = QtGui.QFont(self.scale_fontname, int(self.scale_fontsize))
        fm = QtGui.QFontMetrics(font)

        pen_shadow = QtGui.QPen()

        pen_shadow.setBrush(self.ScaleValueColor)
        painter.setPen(pen_shadow)

        text_radius_factor = 0.8
        text_radius = self.widget_diameter / 2 * text_radius_factor

        scale_per_div = ((self.value_max - self.value_min) / self.scala_main_count)

        angle_distance = (float(self.scale_angle_size) / float(self.scala_main_count))
        for i in range(self.scala_main_count + 1):
            # text = str(int((self.value_max - self.value_min) / self.scala_main_count * i))
            val = self.value_min + scale_per_div * i
            if abs(val) > 1e6 or (abs(val) < 1e-1 and val != 0):
                text = str('%.1e' % (val))
            else:
                if self.decimals:
                    text = str('%.1f' % (val))
                else:
                    text = str('%d' % (int(val)))
            w = fm.width(text) + 1
            h = fm.height()
            painter.setFont(QtGui.QFont(self.scale_fontname, int(self.scale_fontsize)))
            angle = angle_distance * i + float(self.scale_angle_start_value - self.angle_offset)
            x = text_radius * math.cos(math.radians(angle))
            y = text_radius * math.sin(math.radians(angle))
            # print(w, h, x, y, text)
            text = [x - int(w / 2), y - int(h / 2), int(w), int(h), QtCore.Qt.AlignCenter, text]
            painter.drawText(int(text[0]), int(text[1]), int(text[2]), int(text[3]), text[4], text[5])

    # painter.restore()

    def create_fine_scaled_marker(self):
        #  Description_dict = 0
        my_painter = QtGui.QPainter(self)

        my_painter.setRenderHint(QtGui.QPainter.Antialiasing)
        # Koordinatenursprung in die Mitte der Flaeche legen
        my_painter.translate(int(self.width() / 2), int(self.height() / 2))

        my_painter.setPen(QtGui.QColor("black"))
        my_painter.rotate(self.scale_angle_start_value - self.angle_offset)
        steps_size = (float(self.scale_angle_size) / float(self.scala_main_count * self.scala_subdiv_count))
        scale_line_outer_start = self.widget_diameter / 2
        scale_line_lenght = (self.widget_diameter / 2) - (self.widget_diameter / 40)
        for i in range((self.scala_main_count * self.scala_subdiv_count) + 1):
            my_painter.drawLine(int(scale_line_lenght), 0, int(scale_line_outer_start), 0)
            my_painter.rotate(steps_size)

    def create_values_text(self):
        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing)
        # painter.setRenderHint(QtGui.QPainter.Antialiasing)

        # Koordinatenursprung in die Mitte der Flaeche legen
        painter.translate(int(self.width() / 2), int(self.height() / 2))
        # painter.save()
        # xShadow = 3.0
        # yShadow = 3.0
        font = QtGui.QFont(self.value_fontname, int(self.value_fontsize))
        fm = QtGui.QFontMetrics(font)

        pen_shadow = QtGui.QPen()

        pen_shadow.setBrush(self.DisplayValueColor)
        painter.setPen(pen_shadow)

        text_radius = self.widget_diameter / 2 * self.text_radius_factor

        # angle_distance = (float(self.scale_angle_size) / float(self.scala_main_count))
        # for i in range(self.scala_main_count + 1):
        if self.decimals:
            text = str('%.2f' % (self.value))
        else:
            text = str('%d' % (self.value))
        w = fm.width(text) + 1
        h = fm.height()
        painter.setFont(QtGui.QFont(self.value_fontname, int(self.value_fontsize)))

        # Mitte zwischen Skalenstart und Skalenende:
        # Skalenende = Skalenanfang - 360 + Skalenlaenge
        # Skalenmitte = (Skalenende - Skalenanfang) / 2 + Skalenanfang
        angle_end = float(self.scale_angle_start_value + self.scale_angle_size - 360)
        angle = (angle_end - self.scale_angle_start_value) / 2 + self.scale_angle_start_value

        x = text_radius * math.cos(math.radians(angle))
        y = text_radius * math.sin(math.radians(angle))
        # print(w, h, x, y, text)
        text = [x - int(w / 2), y - int(h / 2), int(w), int(h), QtCore.Qt.AlignCenter, text]
        painter.drawText(int(text[0]), int(text[1]), int(text[2]), int(text[3]), text[4], text[5])

    # painter.restore()

    def create_title_text(self):
        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing)
        painter.translate(int(self.width() / 2), int(self.height() / 2))
        font = QtGui.QFont(self.value_fontname, int(self.value_fontsize))
        fm = QtGui.QFontMetrics(font)
        pen_shadow = QtGui.QPen()
        pen_shadow.setBrush(self.DisplayTitleColor)
        painter.setPen(pen_shadow)
        text_radius = self.widget_diameter / 2 * self.text_radius_factor
        text = self.title_text
        w = fm.width(text) + 1
        h = fm.height()
        painter.setFont(QtGui.QFont(self.value_fontname, int(self.value_fontsize)))
        angle_end = float(self.scale_angle_start_value + self.scale_angle_size - 360)
        angle = (angle_end - self.scale_angle_start_value) / 2 + self.scale_angle_start_value

        x = text_radius * math.cos(math.radians(angle))
        y = text_radius * math.sin(math.radians(angle))
        text = [x - int(w / 2), y - int(self.widget_diameter / 1.5), int(w), int(h), QtCore.Qt.AlignCenter, text]
        painter.drawText(int(text[0]), int(text[1]), int(text[2]), int(text[3]), text[4], text[5])

    # painter.restore()

    def draw_big_needle_center_point(self, diameter=30):
        painter = QtGui.QPainter(self)
        # painter.setRenderHint(QtGui.QtGui.QPainter.HighQualityAntialiasing)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)

        # Koordinatenursprung in die Mitte der Flaeche legen
        painter.translate(int(self.width() / 2), int(self.height() / 2))
        painter.setPen(QtCore.Qt.NoPen)
        # painter.setPen(QtCore.Qt.NoPen)
        painter.setBrush(self.CenterPointColor)
        # diameter = diameter # self.widget_diameter/6
        painter.drawEllipse(int(-diameter / 2), int(-diameter / 2), int(diameter), int(diameter))

    def draw_needle(self):
        painter = QtGui.QPainter(self)
        # painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        # Koordinatenursprung in die Mitte der Flaeche legen
        painter.translate(int(self.width() / 2), int(self.height() / 2))
        painter.setPen(QtCore.Qt.NoPen)
        painter.setBrush(self.NeedleColor)
        painter.rotate(((self.value - self.value_offset - self.value_min) * self.scale_angle_size /
                        (self.value_max - self.value_min)) + 90 + self.scale_angle_start_value)

        painter.drawConvexPolygon(self.value_needle[0])

    ###############################################################################################
    # Events
    ###############################################################################################

    def resizeEvent(self, event):
        self.rescale_method()

    def paintEvent(self, event):
        # Main Drawing Event:
        # Will be executed on every change

        # colored pie area
        if self.enable_filled_Polygon:
            self.draw_bg()
            self.draw_filled_polygon()

        # draw scale marker lines
        if self.enable_fine_scaled_marker:
            self.create_fine_scaled_marker()
        if self.enable_big_scaled_marker:
            self.draw_big_scaled_markter()

        # draw scale marker value text
        if self.enable_scale_text:
            self.create_scale_marker_values_text()

        # Display Value
        if self.enable_value_text:
            self.create_values_text()

        # draw needle 1
        if self.enable_Needle_Polygon:
            self.draw_needle()

        # Draw Center Point
        if self.enable_CenterPoint:
            self.draw_big_needle_center_point(diameter=(self.widget_diameter / 6))

        # Display Title
        if self.enable_title_text:
            self.create_title_text()

    ###############################################################################################
    # MouseEvents
    ###############################################################################################

    def setMouseTracking(self, flag):
        def recursive_set(parent):
            for child in parent.findChildren(QtCore.QObject):
                try:
                    child.setMouseTracking(flag)
                except:
                    pass
                recursive_set(child)

        QtWidgets.QWidget.setMouseTracking(self, flag)
        recursive_set(self)

    def mouseReleaseEvent(self, QMouseEvent):
        # print("released")
        self.NeedleColor = self.NeedleColorReleased

        if not self.use_timer_event:
            self.update()
        pass

    def mouseMoveEvent(self, event):
        x, y = event.x() - (self.width() / 2), event.y() - (self.height() / 2)
        if not x == 0:
            angle = math.atan2(y, x) / math.pi * 180
            # winkellaenge der anzeige immer positiv 0 - 360deg
            # min wert + umskalierter wert
            value = (float(math.fmod(angle - self.scale_angle_start_value + 720, 360)) / \
                     (float(self.scale_angle_size) / float(self.value_max - self.value_min))) + self.value_min
            temp = value
            fmod = float(math.fmod(angle - self.scale_angle_start_value + 720, 360))
            state = 0
            if (self.value - (self.value_max - self.value_min) * self.value_needle_snapzone) <= \
                    value <= \
                    (self.value + (self.value_max - self.value_min) * self.value_needle_snapzone):
                self.NeedleColor = self.NeedleColorDrag
                state = 9
                if value >= self.value_max and self.last_value < (self.value_max - self.value_min) / 2:
                    state = 1
                    value = self.value_max
                    self.last_value = self.value_min
                    self.valueChanged.emit(value)
                elif value >= self.value_max >= self.last_value:
                    state = 2
                    value = self.value_max
                    self.last_value = self.value_max
                    self.valueChanged.emit(value)
                else:
                    state = 3
                    self.last_value = value
                    self.valueChanged.emit(value)


