########################################################################################
#                                                                                      #
#   Author: Herve Menager,                                                             #
#   Organization:'Biological Software and Databases' Group, Institut Pasteur, Paris.   #
#   Distributed under GPLv2 Licence. Please refer to the COPYING.LIB document.         #
#                                                                                      #
########################################################################################
import os
import logging
from lxml import etree
from Mobyle.ConfigManager import Config
from Mobyle.Utils import indent

_cfg = Config()
log = logging.getLogger('mobyle.registry' )

class InterfacePreprocessor(object):
    """
    InterfacePreprocessor is a component that generates the pre-computed parts of the MobylePortal interface, i.e., form and
    job pages, workflow graphs, etc.
    """
    
    def __init__(self):
        self.load_xsl_pipe()
        
    def load_xsl_pipe(self):
        """
        Preload all necessary xsl files and define the xsl processing pipeline
        """
        self.XslPipe = []
        local_categories_path = os.path.join(_cfg.mobylehome() , "Local", "categories.xml")
        if os.path.exists(local_categories_path):
            local_categories_url = os.path.join("file://",local_categories_path)
            style0 = etree.parse(os.path.join(_cfg.portal_path(), "xsl", "localize.xsl"))
            self.localize_style = etree.XSLT(style0)
            self.XslPipe.append((self.localize_style, {'localCategoriesUrl':"'"+local_categories_url+"'"}))
        style1bis = etree.parse(os.path.join(_cfg.portal_path(), "xsl", "clean_import.xsl"))
        self.clean_style = etree.XSLT(style1bis)
        style1 = etree.parse(os.path.join(_cfg.portal_path(), "xsl", "parameters.xsl"))
        self.param_style = etree.XSLT(style1)
        style2 = etree.parse(os.path.join(_cfg.portal_path(), "xsl", "layout.xsl"))
        self.layout_style = etree.XSLT(style2)
        style3 = etree.parse(os.path.join(_cfg.portal_path(), "xsl", "annotate.xsl"))
        self.ann_style = etree.XSLT(style3)
        style4 = etree.parse(os.path.join(_cfg.portal_path(), "xsl", "results.xsl"))
        self.res_style = etree.XSLT(style4)
        style5 = etree.parse(os.path.join(_cfg.portal_path(), "xsl", "graphviz_simplify.xsl"))
        self.gvz_style = etree.XSLT(style5)
        self.XslPipe += [
                (self.clean_style, {}),
                (self.param_style, {'previewDataLimit':str(_cfg.previewDataLimit()),'programUri':''}),
                (self.layout_style, {'type':"'form'",'programUri':''}),
                (self.layout_style, {'type':"'viewer'",'programUri':''}),
                (self.res_style, {'previewDataLimit':str(_cfg.previewDataLimit())}),
                (self.ann_style, {}),
                (self.gvz_style, {}),
                (self.layout_style, {'type':"'job_input'"}),
                (self.layout_style, {'type':"'job_output'"})
                ]

    
    def process_interface(self, programpath):
        """
        Pre-process the xsl on program xml definitions
        @param programpath : xml path file to process
        @type programpath : string
        @return: if the processing run well or not
        @rtype: boolean
        """        
        doc = etree.parse(programpath)
        if doc.getroot().tag=='workflow':
            from Mobyle.Workflow import Parser
            from Mobyle.WorkflowLayout import layout
            p = Parser()
            w = p.parse(programpath)
            i_l_s = layout(w) # graph layout as an svg string
            i_l_e = etree.XML(i_l_s) # graph layout as an element
            h = w.find("head")
            if h is None:
                h = etree.SubElement(w,'head') # graph interface container element
            g_i = w.find("head/interface[@type='graph']")
            if g_i is None:
                g_i = etree.SubElement(w.find('head'),'interface') # graph interface container element
            g_i.clear()
            g_i.set("type","graph")
            g_i.append(i_l_e)
            fileResult = open(programpath,"w")
            fileResult.write(etree.tostring(w, pretty_print=True))
            fileResult.close()
            doc = etree.parse(programpath)

        for style, params in self.XslPipe:
            for p in params.keys():
                if p == 'programUri':
                    params[p] = "'"+programpath+"'"
                    log.debug('programUri=%s' % programpath)
            result = style(doc, **params)
            doc = result

        #write the result on the xml itself
        try:
            fileResult = open(programpath,"w")
            indent(doc.getroot())
            fileResult.write(str(doc))
            fileResult.close()
            return True
        except IOError, ex:
            log.error("Problem with the html generation: %s." % ex)
            return False  
