## ------------------------------------------------------------------------
## iSiLK - A python-based graphical user interface for SiLK
## ------------------------------------------------------------------------
## Copyright (c) 2007-2008 Carnegie Mellon University. All Rights Reserved.
## ------------------------------------------------------------------------
## Authors: Andrew Kompanek (ajk@cert.org)
## ------------------------------------------------------------------------
## GNU General Public License (GPL) Rights pursuant to Version 2, June 1991
## Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013
## ------------------------------------------------------------------------
## See the LICENSE file included in this distribution
## ------------------------------------------------------------------------

import wx, ws
import logging
import silk
import tools
import resultset
import pdb


str_help = "Specify an arbitrary command line string to execute \
on the analysis system.  Use the strings $input and $output to refer \
to the input and output files respectively."

class ShellDialog(wx.Dialog):
    def __init__(self, parentResult, parent,
            toolCategory = tools.TC_ANALYSIS,
            *args, **kargs):
        wx.Dialog.__init__(self, parent, -1, *args, **kargs)
        self.txtCommand = ws.XSmTextCtrl(self, -1, "", size=(480,-1))
        help = ws.XSmStaticText(self, -1, str_help) 
        help.Wrap(400)
        # Output format choice
        self.rbAnalysis = wx.RadioButton(self, -1,
                "Analysis tool", style = wx.RB_GROUP)
        self.rbFilter = wx.RadioButton(self, -1,
                "Filter tool (SiLK binary output)")
        self.rbAnalysis.SetValue(True)
        # Create buttons
        sz = wx.BoxSizer(wx.HORIZONTAL)
        sz.Add(wx.Button(self, wx.ID_CANCEL, "Cancel"), flag=wx.ALL, border=10)
        btnCreate = wx.Button(self, wx.ID_OK, "Run Analysis") #, (110,-1), (100,-1))
        sz.Add(btnCreate, flag=wx.ALL, border=10)
        # Create is default button
        btnCreate.SetDefault()
        # Escape key or close causes cancel
        self.SetEscapeId(wx.ID_CANCEL)
        szDlg = wx.BoxSizer(wx.VERTICAL)
        szDlg.Add(wx.StaticText(self, -1, "Output format"), flag=wx.TOP|wx.LEFT|wx.RIGHT, border=6)                
        szDlg.Add(self.rbAnalysis, flag=wx.ALL, border=8)
        help1 = ws.XSmStaticText(self, -1, "The command line tool writes pipe-delimited ascii output to $output.")
        szDlg.Add(help1, flag=wx.LEFT|wx.RIGHT, border=16)
        szDlg.Add(self.rbFilter, flag=wx.ALL, border=8)        
        help2 = ws.XSmStaticText(self, -1, "The command line tool writes binary output to $output.")
        szDlg.Add(help2, flag=wx.LEFT|wx.RIGHT, border=16)
        szDlg.Add(wx.StaticText(self, -1, "Command line"), flag=wx.TOP|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=6)        
        szDlg.Add(help, flag=wx.LEFT|wx.RIGHT, border=8)
        szDlg.Add(self.txtCommand, flag=wx.ALL|wx.EXPAND, border=8)
        szDlg.Add(sz, flag=wx.ALL, border=8)
        self.SetSizerAndFit(szDlg)
        self.txtCommand.SetFocus()
        
    def GetOptions(self):
        opts = {} 
        opts["command-line"] = self.txtCommand.GetValue()
        if self.rbAnalysis.GetValue():
            opts["output-format"] = "text"
        else:
            opts["output-format"] = "binary"
        return opts
        
    def SetOptions(self, opts):
        if "command-line" in opts:
            self.txtCommand.SetValue(opts["command-line"])
            
    def GetResultName(self):
        return "Untitled %s result" % self.txtCommand.GetValue().split()[0]


class ShellTool(tools.AnalysisTool):
    def __init__(self, **kargs):
        tools.AnalysisTool.__init__(self, **kargs)
        
    def CreateDialog(parentResult, parent, title):
         return ShellDialog(parentResult, parent, title=title)
    CreateDialog = staticmethod(CreateDialog)
        
    def CanRun(parentResult):
        return True
        if parentResult == None:
            return True
        return parentResult.IsFilterResult()
    CanRun = staticmethod(CanRun)
    
    def _GetToolName():
        return "shell tool"
    _GetToolName = staticmethod(_GetToolName)
    
    def _GetResultClass(self):
        if self.opts["output-format"] == "text":
            return resultset.ToolResult
        else:
            return resultset.FilterResult

    def _GetResultName(self):
        return "shell result"

    def _GetCommandLines(inputFileName, outputFileName, **kargs):
        print "kargs is %s" % kargs
        cmd = kargs.get("command-line", "(Command Line Unknown)")
        if inputFileName:
            cmd = cmd.replace("$input", inputFileName)
        cmd = cmd.replace("$output", outputFileName)
        return cmd 
    _GetCommandLines = staticmethod(_GetCommandLines)
  
    def _RunAnalysis(self, context, inputFileName, outputFileName):
        # Build the command line
        print "running with options %s" % self.opts
        #self.command = self._buildCommandLine(self.opts["command-line"],
        #    inputFileName, outputFileName)
        self.command = ShellTool._GetCommandLines(inputFileName, outputFileName, **self.opts)
        cmd = silk._build_commandline(context.runRemote, self.command, cmdDir=context.runDir)
        context._LogCommand(cmd)
        f = silk.exec_command(context, cmd + "")
        output = f.readlines()
        if f.close():
            raise silk.CommandError("Error running command", "%s\n\n%s" % (cmd, "".join(output)))
        # Get the file size (FIXME put in framework)
        if self.opts["output-format"] == "binary":
            # Verify it's rwfilter output
            info = silk.fileinfo(context, outputFileName)            
            print "=== Read info: %s" % info            
            silk.cut(context, outputFileName, outputFileName+".asc")
        else:
            # Verify it's NOT rwfilter output
            try:
                #pdb.set_trace()
                info = silk.fileinfo(context, outputFileName)
            except:
                return
            raise silk.CommandError("Unexpected output",
                "Output file appears to be an rwfilter binary file rather than a text file.")


# Register myself
print "Registering shell tool"
tools.RegisterPlugin("Shell...", "icons/tool.gif", ShellTool, "Filter")
