# -*- coding: utf-8 -*-
#
# ccwatcher (http://ccwatcher.sourceforge.net/)
# Copyright (C) 2009-2013 Xaver Wurzenberger <xaverxn at users.sourceforge.net>
#
# This program is free software; you can redistribute and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, 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 PyQt4 import QtCore, QtGui, Qwt5


class CcwQwtPlotter(QtGui.QWidget):
    
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        
        self.pltr = Qwt5.QwtPlot()
        self.pltr.setCanvasBackground(QtCore.Qt.white)
        self.pltr.plotLayout().setCanvasMargin(0)
        self.pltr.plotLayout().setAlignCanvasToScales(True)
        self.pltr.enableAxis(Qwt5.QwtPlot.yRight)
        self.pltr.axisScaleEngine(Qwt5.QwtPlot.xBottom).setMargins(0.1, 0.1) #do this procentually and update on replot
        self.pltr.axisScaleEngine(Qwt5.QwtPlot.yLeft).setMargins(0.01, 0.01) #alternative way would be: self.pltr.setMargin(100) 
        self.dummylayouthbox = QtGui.QHBoxLayout()
        self.dummylayouthbox.addWidget(self.pltr)
        self.setLayout(self.dummylayouthbox)

        grid = Qwt5.QwtPlotGrid()
        pen = QtGui.QPen(QtCore.Qt.DotLine)
        pen.setColor(QtCore.Qt.black)
        pen.setWidth(0)
        grid.setPen(pen)
        grid.attach(self.pltr)
        
        self.list_curves = []
        self.list_qtcolors = [ QtCore.Qt.darkBlue,  #0
                                        QtCore.Qt.green,
                                        QtCore.Qt.yellow, 
                                        QtCore.Qt.cyan,
                                        QtCore.Qt.darkMagenta,
                                        QtCore.Qt.darkCyan,
                                        QtCore.Qt.darkGray,
                                        QtCore.Qt.darkGreen,
                                        QtCore.Qt.darkRed,
                                        QtCore.Qt.gray,
                                        QtCore.Qt.lightGray,   
                                        QtCore.Qt.magenta,
                                        QtCore.Qt.darkYellow,
                                        QtCore.Qt.blue,
                                        QtCore.Qt.black ]     #14
    
        legend = Qwt5.QwtLegend()
#        legend.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Sunken)
#        legend.setItemMode(Qwt5.QwtLegend.ClickableItem)
        self.pltr.insertLegend(legend, Qwt5.QwtPlot.BottomLegend)
                                        
        self.connect(self.pltr.axisWidget(Qwt5.QwtPlot.yLeft), QtCore.SIGNAL("scaleDivChanged()"), self.syncYScales)
        self.connect(self.pltr.axisWidget(Qwt5.QwtPlot.xBottom), QtCore.SIGNAL("scaleDivChanged()"), self.saveXScale)
        
        self.__initZooming()
        
        self.currentX0 = 0 #needed by plotter for rescaling
        self.currentX1 = 0
        self.currentY0 = 0
        self.currentY1 = 0


    def syncYScales(self):
        self.pltr.setAxisScaleDiv(Qwt5.QwtPlot.yRight, self.pltr.axisScaleDiv(Qwt5.QwtPlot.yLeft))
        self.currentY0 = self.pltr.axisScaleDiv(Qwt5.QwtPlot.yRight).lowerBound()
        self.currentY1 = self.pltr.axisScaleDiv(Qwt5.QwtPlot.yRight).upperBound()


    def saveXScale(self):
        self.currentX0 = self.pltr.axisScaleDiv(Qwt5.QwtPlot.xBottom).lowerBound()
        self.currentX1 = self.pltr.axisScaleDiv(Qwt5.QwtPlot.xBottom).upperBound()


    def __initZooming(self):
        """Initialize zooming
        """

        self.zoomer = Qwt5.QwtPlotZoomer(Qwt5.QwtPlot.xBottom,
                                        Qwt5.QwtPlot.yLeft,
                                        Qwt5.QwtPicker.DragSelection,
                                        Qwt5.QwtPicker.AlwaysOff,
                                        self.pltr.canvas())
        self.zoomer.setRubberBandPen(QtGui.QPen(QtCore.Qt.black))
        pattern = [
                Qwt5.QwtEventPattern.MousePattern(QtCore.Qt.LeftButton,
                                                 QtCore.Qt.NoModifier),
                Qwt5.QwtEventPattern.MousePattern(QtCore.Qt.MidButton,
                                                 QtCore.Qt.NoModifier),
                Qwt5.QwtEventPattern.MousePattern(QtCore.Qt.RightButton,
                                                 QtCore.Qt.NoModifier),
                Qwt5.QwtEventPattern.MousePattern(QtCore.Qt.LeftButton,
                                                 QtCore.Qt.ShiftModifier),
                Qwt5.QwtEventPattern.MousePattern(QtCore.Qt.MidButton,
                                                 QtCore.Qt.ShiftModifier),
                Qwt5.QwtEventPattern.MousePattern(QtCore.Qt.RightButton,
                                                 QtCore.Qt.ShiftModifier),
                ]
        self.zoomer.setMousePattern(pattern)



    def plot(self):
        
        for plotitem in self.pltr.itemList():
            if isinstance(plotitem, Qwt5.QwtPlotCurve):
                plotitem.detach()
                
        for curve in self.list_curves:
            curve.attach(self.pltr)
        
#        currZoom = self.zoomer.zoomRect()
        self.clearZoomStack()
#        if currZoom != QtCore.QRectF(0.0, 0.0, 1000.0, 1000.0) and newmode == False:
        newZoom = QtCore.QRectF(0.0, 0.0, 0.0,  0.0)
        #print newZoom.isValid()
        newZoom.setLeft(self.proposedX00)
        newZoom.setTop(self.proposedY00)
        newZoom.setRight(self.proposedX11)
        newZoom.setBottom(self.proposedY11)
        self.zoomer.zoom(newZoom)
        #print "Zooming to 100% and setting zoom base and replotting... proposed: ",newZoom
        self.zoomer.setZoomBase()
        #print self.zoomer.zoomRect()#, self.pltr.axisScaleDiv(Qwt5.QwtPlot.yLeft).range()
        #self.pltr.replot()
        #print self.zoomer.zoomRect()
        
        newZoom.setLeft(self.proposedX0)
        newZoom.setRight(self.proposedX1)
        newZoom.setBottom(self.proposedY0)
        newZoom.setTop(self.proposedY1)
        self.zoomer.zoom(newZoom)
        #self.pltr.replot()
        #print "Zoomed to ", self.proposedY0, "&", self.proposedY1
        
        


    def clearZoomStack(self):
        """Auto scale and clear the zoom stack
        """
#        self.pltr.axisScaleEngine(Qwt5.QwtPlot.xBottom).setMargins(0.1,0.1) #do this procentually and update on replot
#        self.pltr.axisScaleEngine(Qwt5.QwtPlot.yLeft).setMargins(0.01,0.01)
        self.pltr.setAxisAutoScale(Qwt5.QwtPlot.xBottom)
        self.pltr.setAxisAutoScale(Qwt5.QwtPlot.yLeft)
        #self.pltr.replot()
        self.zoomer.setZoomBase()



    def setXAxisLabel(self, str_label):
        self.pltr.setAxisTitle(Qwt5.QwtPlot.xBottom, str_label)


    def setYAxisLabel(self, str_label):
        self.pltr.setAxisTitle(Qwt5.QwtPlot.yLeft, str_label)


    def setTitle(self,  str_title):
        self.pltr.setTitle(str_title)


    def setProposedScale(self,  x00,  x11, y00, y11, x0, x1, y0, y1, xmargin, ymargin):
        #print "PROP: ", x00, x11, y00, y11, x0, x1, y0, y1
        self.proposedX0 = x0
        self.proposedX00 = x00
        self.proposedX1 = x1
        self.proposedX11 = x11
        self.proposedY0 = y0
        self.proposedY00 = y00
        self.proposedY1 = y1
        self.proposedY11 = y11
        self.pltr.axisScaleEngine(Qwt5.QwtPlot.xBottom).setMargins(xmargin, xmargin) #we need to set the margins big enough, otherwise we cannot zoom out!
        self.pltr.axisScaleEngine(Qwt5.QwtPlot.yLeft).setMargins(ymargin, ymargin)


    def commands(self, *args):
        pass #some gnuplot-specific stuff is still parsed to the commands() interface, so this dummy is needed


    def flushdata(self):
        self.list_curves = []


    def data(self, listolists, xcolumn, ycolumn, str_legendtitle):
        newcurve = Qwt5.QwtPlotCurve(str_legendtitle)
        newcurve.setStyle(Qwt5.QwtPlotCurve.Lines)
        int_numcurves = len(self.list_curves)
        if int_numcurves == 0:
            crosscolor = QtCore.Qt.red
            linecolor = QtCore.Qt.black
        else:
            while int_numcurves > 15: #test if this works!
                int_numcurves = int_numcurves-15
            crosscolor = self.list_qtcolors[int_numcurves-1]
            linecolor = QtCore.Qt.gray
        newcurve.setPen(QtGui.QPen(linecolor))
        newcurve.setSymbol(Qwt5.QwtSymbol(Qwt5.QwtSymbol.Cross,
                                                                    QtGui.QBrush(),
                                                                    QtGui.QPen(crosscolor),
                                                                    QtCore.QSize(5, 5)))
        list_xval = map(lambda x : x[xcolumn-1], listolists)
        list_yval = map(lambda x : x[ycolumn-1], listolists)
        newcurve.setData(list_xval, list_yval)
        self.list_curves.append(newcurve)




