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

# This python module is an adapted version of the interface from GaussSum (http://gausssum.sf.net) which is Copyright (C) 2006-2009 Noel O'Boyle <baoilleach@gmail.com> and under the terms of the GNU GPLicense as published by the Free Software Foundation version 2 or later version.


"""ccw_gnupy.py
"""

import os
import sys
import subprocess
import string # needed for string.replace in windows pathname normalizer
from tempfile import mkstemp

class Gnuplot(object):
    """Simple interface to Gnuplot that uses subprocess.Popen().

    >>> g = Gnuplot()
    >>> g.data( [(1,0.5),(2,1.9),(3,1)], 1, 2, "mytitle" )
    >>> g.commands("set title 'Testing'")
    >>> g.plot()
    
    - self.settings is a list with all the "raw" gnuplot commands like: ["set terminal dumb","set title 'Testing'", "plot '/tmp/s66hn1' with lines"]
    - self.plotcommands collects just the tempfilenames (which contain the actual data) and styles, like : ['"/tmp/s66hn1" with lines','"/tmp/uii7z3" with linespoints']
    - plot() closes and removes its files on its own, while the data files are closed and deleted by __del__
    - The actual where-to-write-the-png--filename is just used once at the beginning of plot(): To write 'set output "%s"' % self._fixname(filename)to self.settings
    """


    def __init__(self, gnuplotexec = None):
        """Initialise the Gnuplot object.

          gnuplotexec: the location of the gnuplot executable (optional)
        """
        if not gnuplotexec:
            if sys.platform.startswith('win'):
                self.gnuplotexec = "pgnuplot.exe"
            else:
                self.gnuplotexec = "gnuplot"
        else:
            self.gnuplotexec = gnuplotexec
        self.list_filedes = []
        self.list_datafiles = []
        self.plotcommands = []
        self.settings = []
        self.gui = False


    def commands(self,*listofcommands):
        """Add a list of commands for the plot."""
        for command in listofcommands:
            if 'set term png' in command:
                self.gui = True
        self.settings.extend(listofcommands)


    def data(self, listolists, int_xcolumn, int_ycolumn, str_legendtitle):
        """Save the data to a temporary file and appends stuff to self.list_datafiles and self.plotcommands."""

        filedes, datafilename = mkstemp()

        output = open(datafilename,"w")
        for line in listolists:
            convertedline = map(str, line)
            output.write("\t".join(convertedline)+"\n")
        output.close()

    #old: self.str_gnuplot_linetype_preserved = 'linespoints pt 15 lt 15'
        if len(self.list_datafiles) == 0:
            if self.gui == True:
                style = 'using '+str(int_xcolumn)+':'+str(int_ycolumn)+' title "'+str_legendtitle+'" with linespoints'
            else:
                style = 'using '+str(int_xcolumn)+':'+str(int_ycolumn)+' title "'+str_legendtitle+'" with linespoints pt -22 lt 0'
        else:
            style = 'using '+str(int_xcolumn)+':'+str(int_ycolumn)+' title "'+str_legendtitle+'" with linespoints'
        self.plotcommands.append( '"%s" %s' % (self._fixname(datafilename),style)) #they pile up -> parser should call flushdata() when necessary

        self.list_datafiles.append(datafilename)
        self.list_filedes.append(filedes)
#        print "LEN Data: ",self.list_datafiles



    def plot(self):
        """Plot the graph."""
        
        self.filedes, self.scriptfilename = mkstemp()
        output = open(self.scriptfilename,"w")
        output.write("\n".join(self.settings))
        output.write("\n")
        output.write('plot %s \n' % ",".join(self.plotcommands)) #maybe use string instead of list for plotcommands
        output.close()
        
#        print self.scriptfilename, ": ", os.access(self.scriptfilename, os.R_OK) 
        status = subprocess.call((self.gnuplotexec,self.scriptfilename))
        
        #self.plotcommands = [] #this was so stuff would not pile up -> now parser calls flushdata(). This way replots are possible
        os.close(self.filedes) #This is important! The only job of the filedes is this: closing on OS level so we can remove the tempfile afterwards...
        os.remove(self.scriptfilename)
        return status


    def setTitle(self, str_title):
        self.commands('set title "'+str_title+'"') #or better write ---self.settings.extend('set title "'+str_title+'"')---?


    def setXAxisLabel(self,  str_label):
        self.commands('set xlabel "'+str_label+'"')


    def setYAxisLabel(self,  str_label):
        self.commands('set ylabel "'+str_label+'"')


    def flushdata(self):
        """This removes the old datafiles and plotcommands (and thus styles) so they don't pile up in case of a set_plot_mode/replot/...
            The scriptfiles are removed by self.plot() itself automatically.
            Mind that the settingsfile is not reseted. Do we need a flushsettings() command?"""
        self.plotcommands = []
        try:
            for entry in self.list_filedes:
                os.close(entry)
            for entry in self.list_datafiles:
                os.remove(entry)
            self.list_filedes = []
            self.list_datafiles = []
        except:
            print "FIXME: Something went wrong closing the old files (Gnupy, os.close(filedes), os.remove(datafile), emptying lists) ..."
        

    def _fixname(self,filename): # Still needed for the tempfile names! Or move getPlotPath() here?
        """Replace " and \ by their escaped equivalents."""
        # Taken from gnuplot-py (Michael Haggerty)
        for c in ['\\', '\"']:
            filename = string.replace(filename, c, '\\' + c)

        return filename
