# -*- coding: iso-8859-1 -*-
"""
    MoinMoin - GNUPLOT Command Data Parser

    @copyright: 2008 MoinMoin:KwonChanYoung at europython2008
    @license: GNU GPL, see COPYING for details.
"""

"""
    example:   {{{#!gnuplot
                ...
                ...
                }}}
"""

import os
import sys
import base64
import string
import StringIO
import exceptions
import codecs
import tempfile
import subprocess
import time
import ctypes
import sha

from MoinMoin import config
from MoinMoin.action import AttachFile
from MoinMoin import log
loggin = log.getLogger(__name__)

# After checking that the gnuplot has been installed successfully,
# Register executable
GnuPlotExe = '/usr/local/bin/gnuplot'
TempDir = '/dev/shm'

Dependencies = []

class Parser:
    """
        Sends plot image generated by gnuplot
    """
    
    extensions = []
    Dependencies = Dependencies

    def __init__(self, raw, request, **kw):
        self.raw = raw
        self.request = request

    def format(self, formatter):
        """ Send the text. """
        self.request.flush() # to identify error text

        img_name = sha.new(self.raw).hexdigest()
        img_name = 'gnuplot_' + img_name + "_chart.img"

        self.pagename = formatter.page.page_name
        url = AttachFile.getAttachUrl(self.pagename, img_name, self.request)
        self.attach_dir=AttachFile.getAttachDir(self.request,self.pagename,create=1)

        self.delete_old_charts(formatter)

        if not os.path.isfile(self.attach_dir + '/' + img_name):
            img_data = self.gnuplot(self.raw.splitlines())
            attached_file = file(self.attach_dir + '/' + img_name, 'wb')
            attached_file.write(img_data)
            attached_file.close()

        self.request.write(formatter.image(src="%s" % url, alt=self.raw))

    def delete_old_charts(self, formatter):
        page_info = formatter.page.lastEditInfo()
        try:
            page_date = page_info['time']
        except exceptions.KeyError, ex:
            return	
        attach_files = AttachFile._get_files(self.request, self.pagename)
        for chart in attach_files:
            if chart.find('gnuplot_') == 0 and chart.find('_chart.img') > 0 :
                fullpath = os.path.join(self.attach_dir, chart).encode(config.charset)
                st = os.stat(fullpath)
                chart_date =  self.request.user.getFormattedDateTime(st.st_mtime)
                if chart_date < page_date :
                    os.remove(fullpath)
            else :
                continue

    def gnuplot(self, command_lines):
        tmpfile = tempfile.NamedTemporaryFile('rw',-1,'','gnuplot_',TempDir)
        cmdfilename = tmpfile.name + '.cmd'
        imgfilename = tmpfile.name + '.img'
        cmdfile = file(cmdfilename, 'w')
        
        # set file
        cmdfile.write('set terminal png size 600,400\n')
        cmdfile.write('set output "' + string.replace(imgfilename, '\\', '/') + '"\n')

        for command in command_lines:
            command = string.strip(command)
            smallcmd = string.lower(command)
            tokens = string.split(smallcmd)
            try:
                if len(tokens) == 0 or command[0] == '#' :
                    cmdfile.write(command + '\n')
                elif len(tokens) > 2 and string.find(tokens[1], 'output') > 0 and tokens[0] == 'set' > 0:
                    cmdfile.write('#' + command + '\n')
                elif len(tokens) > 2 and string.find(tokens[1], 'term') == 0 and tokens[0] == 'set' > 0:
                        cmdfile.write('#' + command + '\n')
                        ## ToDo
                else :
                    cmdfile.write(command + '\n')
            except exceptions.IndexError, ex :
                cmdfile.write(command + '\n')
            cmdfile.flush()
                
        cmdfile.close()
        
        p = subprocess.Popen([GnuPlotExe, cmdfilename])
        if sys.platform == 'win32':
            import win32event
            import win32file
            PROCESS_TERMINATE = 1
            SYNCRONIZE = int('0x00100000', 16)
            handle = ctypes.windll.kernel32.OpenProcess(SYNCRONIZE|PROCESS_TERMINATE, False, p.pid)
            if ctypes.windll.kernel32.WaitForSingleObject(handle, 5000) != win32event.WAIT_OBJECT_0 : # wait up to 5 seconds
                ctypes.windll.kernel32.TerminateProcess(handle,0)
                ctypes.windll.kernel32.CloseHandle(handle)
            try:        
                os.remove(cmdfilename)
            except exceptions.WindowsError, ex:
                pass
            except exceptions.EnvironmentError, ex:
                os.kill(p.pid, 9)

        else :
            try:        
                p.wait()
                os.remove(cmdfilename)
            except exceptions.EnvironmentError, ex:
                os.kill(p.pid, 9)
    
        imgf = file(imgfilename, 'rb')
        raw_data = imgf.read()
        imgf.close()
        os.remove(imgfilename)
            
        return raw_data

if __name__ == '__main__' :
    plotlines=['plot sin(x),cos(x)',]
    plotparser = Parser('','')
    print base64.b64encode(plotparser.gnuplot(plotlines))
    

