# Copyright (c) 2001 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307
# USA.
__revision__ = "$Id: RecipeModel.py,v 1.28 2002/01/04 14:13:05 syt Exp $"

from narval.utils.dp import Observable
from narval.lib import *
from os.path import normpath,join
from RecipeLayout import *
from narval.gui import unicode_to_gtk

class RecipeModel(Observable):
    """
    Model of recipe which contains current modified recipe
    and unmodified recipe if user doesn't want to save
    """
    
    def __init__(self):
        Observable.__init__(self)
        # record the recipe which is going to be modified
        self._unmodified_recipe = None
        # current modified recipe
        self._recipe = None
        # record layout pattern
        self._layout_pattern = RecipeLayout1()

    ## layout functions #######################################################
    def set_layout_pattern(self,lp):
        self._layout_pattern = lp
        self.changes.append(('pattern',))
        self.notify_observers()

    ## get recipe functions ###################################################
    def set_recipe(self,recipe):
        from HornAbstraction import HORNElementsFactory, Document
        print 'set recipe', dir(recipe), id(recipe)
        self.fact = HORNElementsFactory()
        self.fact.create_dom_document()
        data = recipe.as_xml()
        self._recipe = self.fact.element_from_string(data)
        self._unmodified_recipe = self.fact.element_from_string(data)
        # update graphic list before...
        self.new = 1
        self.changes.append(())
        self.notify_observers()

    def update_recipe(self,recipe):
        print '-'*80
        print 'UPDATE RECIPE', dir(recipe), id(recipe)
        self._recipe = recipe
        self.new = 0
        self.changes.append(())
        self.notify_observers()
    
    # edition functions #######################################################
    def add_step(self, id, node=None):
        doc = self._recipe.ownerDocument
        if node:
            node.setAttributeNS(NO_NS, 'id', id)
            self._recipe.appendChild(doc.importNode(node, DEEP_COPY))
        else:
            step = doc.createElementNS(AL_NS, 'al:step')
            step.setAttributeNS(NO_NS, 'target', 'No target')
            step.setAttributeNS(NO_NS, 'id', id)
            self._recipe.appendChild(step)
        self.changes.append(())
        self.notify_observers()

    def remove_step(self,id):
        # remove connections before
        for inref in select_many(self._recipe,'al:transition/al:in[@idref="%s"]'%(id)):
            if inref:
                inref.parentNode.removeChild(inref)
                self.fact.release_domtree(inref)
        for outref in select_many(self._recipe,'al:transition/al:out[@idref="%s"]'%(id)):
            if outref:
                outref.parentNode.removeChild(outref)
                self.fact.release_domtree(outref)
        try:
            step = select_one(self._recipe,'al:step[@id="%s"]'%(id))
            step.parentNode.removeChild(step)
            self.fact.release_domtree(step)
        except:
            import traceback
            traceback.print_exc()
            print unicode_to_gtk(_('step %s not found') % str(id))

        self.changes.append(())
        self.notify_observers()

    def add_transition(self,id,id_in=None,id_out=None):
        transition = self._recipe.ownerDocument.createElementNS(AL_NS,'al:transition')
        transition.setAttributeNS(NO_NS, 'id', id)
        self._recipe.appendChild(transition)
        if id_in:
            link_in = transition.ownerDocument.createElementNS(AL_NS,'al:in')
            link_in.setAttributeNS(NO_NS,'idref',id_in)
            transition.appendChild(link_in)

        if id_out:
            link_out = transition.ownerDocument.createElementNS(AL_NS,'al:out')
            link_out.setAttributeNS(NO_NS,'idref',id_out)
            transition.appendChild(link_out)
        self.changes.append(())
        self.notify_observers()

    def remove_transition(self, id):
        try:
            transition = select_one(self._recipe,'al:transition[@id="%s"]'%(id))
            transition.parentNode.removeChild(transition)
            self.fact.release_domtree(transition)
        except:
            import traceback
            traceback.print_exc()
        self.changes.append(())
        self.notify_observers()

    def add_in_link_to_transition(self,id,id_in):
        transition = select_one(self._recipe,'al:transition[@id="%s"]'%(id))
        link_in = transition.ownerDocument.createElementNS(AL_NS,'al:in')
        link_in.setAttributeNS(NO_NS,'idref',id_in)
        transition.appendChild(link_in)
        self.changes.append(())
        self.notify_observers()

    def add_out_link_to_transition(self,id,id_out):
        transition = select_one(self._recipe,'al:transition[@id="%s"]'%(id))
        link_out = transition.ownerDocument.createElementNS(AL_NS,'al:out')
        link_out.setAttributeNS(NO_NS,'idref',id_out)
        transition.appendChild(link_out)
        self.changes.append(())
        self.notify_observers()        
        
        
    ## change observers #######################################################
    def update_step(self, id, newstep):
        try:
            tmpstep = select_one(self._recipe, 'al:step[@id="%s"]'%(id))
            tmpstep.setAttributeNS(NO_NS, 'state',
                                   newstep.getAttributeNS(NO_NS, 'state'))
            self.changes.append(())
            self.notify_observers()
        except:
            import traceback
            traceback.print_exc()
            print unicode_to_gtk(_('step %s not found') % str(id))

    def update_transition(self, id, newtransition):
        try:
            transition = select_one(self._recipe,'al:transition[@id="%s"]'%(id))
            transition.setAttributeNS(NO_NS, 'state',
                                   newtransition.getAttributeNS(NO_NS, 'state'))
            self.changes.append(())
            self.notify_observers()
        except:
            import traceback
            traceback.print_exc()
