## ------------------------------------------------------------------------
## 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
import logging

_plugins = []

TC_FILTER = 0
TC_ANALYSIS = 1
TC_QUERY = 2
TC_GRAPH = 3
TC_IMPORT = 4
TC_EXPORT = 5
TC_CLIPBOARD_COPY = 6

_current_plugin_id = 0

class ToolDesc(object):
    def __init__(self, toolName, toolIcon, toolClass, toolCategory, opts):
        global _current_plugin_id
        self.toolId = _current_plugin_id
        print "Created new ToolDesc, toolId = %d" % self.toolId
        _current_plugin_id += 1
        if toolIcon == None:
            toolIcon = "icons/tool.gif"
        self.toolName = toolName
        self.toolIcon = toolIcon
        self.toolClass = toolClass
        self.opts = opts

def GetPlugins(category=None):
    _plugins.sort(key = lambda i : i.toolName)
    plugins = []
    for p in _plugins:
        print "Looking at tool %s (%s)" % (p.toolName, p.toolClass.GetCategory())
        if category == None or p.toolClass.GetCategory() == category:
            plugins.append(p)
    return plugins
    
def UnregisterPlugin(toolClass):
    for p in _plugins:
        print "Trying to unregister %s, comparing to %s" % (toolClass._GetToolName(), p.toolClass._GetToolName())
        if toolClass._GetToolName() == p.toolClass._GetToolName():
            print "Found plugin"
            _plugins.remove(p)
            return True
    print "Didn't find plugin"
    return False
    
def FindPluginById(toolId):
    for p in _plugins:
        if p.toolId == toolId:
            return p
    return None

def RegisterPlugin(toolName, toolIcon, toolClass, toolCategory, **opts):
    print "%s -> %s" % (toolName, toolClass)
    print "Plugin name is %s" % toolClass._GetToolName()
    _plugins.append(ToolDesc(toolName, toolIcon, toolClass, toolCategory, opts))
    print "FIrst plugin name is %s" % _plugins[0].toolClass._GetToolName()

# Built-in tools
__all__ = [ "query", "refine", "count", "trend", "split", "shell", "set", "settool", "AnalysisTool" ]

# Superclass for both built-in and plug-in tools
class AnalysisTool(object):
    ''' Abstract superclass for a Tool made available through the iSiLK
        GUI. '''
    def __init__(self, **kargs):
        self.opts = kargs

    def _GetToolName():
        return "Tool"
    
    def _GetToolIcon():
        raise RuntimeError, "Not yet implemented, Drew"
        
    def _GetResultName(self):
        return "Analysis Result"
        
    def _CanRun(self, parentResult):
        ''' Returns True for filter (binary) data result.  Should be overridden
            by a tool subclass if it imposes different preconditions. '''
        return parentResult.IsFilterResult()
    
    def _CreateDialog(self, parentResult, parentWindow):
        ''' By default returns a generic dialog with a Run and Cancel button.
            Should generally be overriden by a tool subclass'''
        raise RuntimeError, "AnalysisTools must override CreateDialog"
        
    def _PreAnalysis(self, context, inputFileName, outputFileName):
        ''' Run *before* the job thread is created. '''
        pass
        
    def _RunAnalysis(self, context, inputFileName, outputFileName):
        ''' The actual analysis function.  This should generally be code based
            on the silk wrapper module, but any code that produces an outputFile
            understood by the ResultClass is possible.  Tools must implement
            this method. '''
        raise RuntimeError, "AnalysisTools must override RunAnalysis"
        
    def _GetResultClass(self):
        ''' Returns the class to use for representing results of an analysis.  
            This method should generally return FilterResult or ToolResult.  
            Subclasses must implement this method. '''
        raise RuntimeError, "AnalysisTools must override _GetResultClass"
        
    def GetCategory():
        ''' A category to display for the user.  Should be one of the
            strings: Query, Filter, Analysis'''
        return "Analysis"
    GetCategory = staticmethod(GetCategory)
        
    def _GetCommandLines(inputFile, outputFile, **kargs):
        ''' Return a string representing the SiLK command line equivalent
            of the analysis (if there is one). '''
        return "(Unknown or unavailable on the commmand line)"
    _GetCommandLines = staticmethod(_GetCommandLines)
    
    def _GetDefaultView(self):
        ''' The default view to create in the problem set explorer.  Most
            tools do not need to override the default implementation. '''
        return views.RecordViewPage
        
    def _waitToComplete(self):
        logging.info("Waiting for processing to complete")
        while self.workerThread:
            self.workerThread.join(5)
        logging.info("Analyis complete (finished waiting)")
                
    def _UpdateStatus(self, loc=None, status=None, percentComplete=None):
        ''' Subclasses may implement _UpdateStatus to update status for
            any child created by the tool. '''
        pass
      
import set  