#!/usr/bin/python3

"""
A complete rewrite of grace_np.py, which was authored by Michael Haggerty
in 1999. This rewrite should provide the same features, while being
more pythonish, and able to run with both Python2 and Python3.
"""

from subprocess import Popen, PIPE
import sys, time

class GraceProcess:
    """Represents a running xmgrace program."""

    def __init__(self, bufsize=-1, debug=0, fixedsize=None, ask=None, safe=True):
        """Start xmgrace, reading from a pipe that we control.

        Parameters:
          bufsize   -- choose the size of the buffer used in the
                       communication.  grace won't act on commands that
                       haven't been flushed from the buffer, but speed
                       should supposedly be better with some buffering.
                       The default is -1, which means the default buffering
                       inherited from the system; 0 means unbuffered,
                       1 means line-buffered, and bigger values mean
                       a buffer of apprimately that size.
          debug     -- when set, each command that is passed to xmgrace is
                       also echoed to stderr.
          fixedsize -- if set to None, the grace window is
                       freely resizable (`-free').  Otherwise set to a
                       tuple, which will set the fixed size of the
                       grace canvas.  (I don't know what units are
                       used.###)
          ask       -- if set, xmgrace will ask before doing `dangerous'
                       things, like overwriting a file or even clearing the
                       display.  Default is not to ask.
          safe      -- True by default; if set, some operations are not
                       available and should trigger error messages, like
                       when saving a file
        """
        self.debug     = debug
        self.fixedsize = fixedsize
        self.ask       = ask
        self.safe      = safe
        
        cmd = ('xmgrace','-dpipe','-')

        if self.fixedsize is None:
            cmd = cmd + ('-free',)
        else:
            cmd = cmd + ('-fixed', repr(self.fixedsize[0]), repr(self.fixedsize[1]))

        if self.ask is None:
            cmd = cmd + ('-noask',)

        if not self.safe:
            cmd = cmd + ('-nosafe',)

        self.p=Popen(cmd,
                     stdin=PIPE, stdout=PIPE, stderr=PIPE,
                     bufsize=bufsize,
                     universal_newlines=True)


    def command(self, cmd):
        """
        Issue a command to grace followed by a newline.

        Unless Popen was called with bufsize=0 or 1, this
        interface is buffered, and command execution may be delayed.
        To flush the buffer, send the command via self(cmd), or call
        self.flush()
        @return stdout, stderr from the pipe
        """
        if self.debug:
            sys.stderr.write('Grace command: "%s"\n' % cmd)
        self.p.stdin.write(cmd+"\n")

    def flush(self):
        """
        Flush the input buffer
        """
        self.p.stdin.flush()

    def __call__(self, cmd):
        """
        Send the command to grace, then flush the write queue.
        @return stdout, stderr from the pipe
        """

        result = self.command(cmd)
        self.p.stdin.flush()
        return result

    def __del__(self):
        """
        kills the thread upon deletion
        """
        self.p.kill()

    def exit(self):
        """
        self-deletion
        """
        self.__del__()
        

if __name__=="__main__":
    g=GraceProcess(debug=True, safe=False)
    
    g('world xmax 100')
    g('world ymax 10000')
    g('xaxis tick major 20')
    g('xaxis tick minor 10')
    g('yaxis tick major 2000')
    g('yaxis tick minor 1000')
    g('s0 on')
    g('s0 symbol 1')
    g('s0 symbol size 0.3')
    g('s0 symbol fill pattern 1')
    g('s1 on')
    g('s1 symbol 1')
    g('s1 symbol size 0.3')
    g('s1 symbol fill pattern 1')
    # Display sample data
    for i in range(1,101):
        g('g0.s0 point %d, %d' % (i, i))
        g('g0.s1 point %d, %d' % (i, i * i))
        # Update the Grace display after every ten steps
        if i % 10 == 0:
            g('redraw')
            # Wait a second, just to simulate some time needed for
            # calculations. Your real application shouldn't wait.
            time.sleep(0.2)

    # Tell Grace to save the data:
    g('saveall "sample.agr"')
