'''This file is a MixIn to make it easier to use FormKit with Webware. You can still use
FormKit (with or without Webware) and NOT use this file, but you will have to do certain
operations more manually.'''

from WebKit.Cookie import Cookie

import time

class FormKitMixIn:
    '''IMPORTANT: This MixIn must be inherited first, because it overwrites methods
    of WebKit. Those methods are preAction and postAction, and are essentially non-
    destructive (no methods that get called stock do not get called here).'''
    
    ## FormKit support stuff ##

    def addForm(self,formInstance):
        '''adds the passed-in form instance to the list of forms self._forms,
        AND sets the numeric id for that appended form instance.'''

        # this method is usually called in a servlet's __init__ (or awake() ) and
        # must be called once for each form in a servlet
        
        # first, make sure that there is a _forms in self
        if not hasattr(self,'_forms'):
            # if it's not, initialize it to an empty list
            self._forms = [ ]
            
        self._forms.append(formInstance)
        num = len(self._forms) - 1
        # yes, _setFormID is a 'private' method, but we're the only one that uses it
        self._forms[-1]._setFormID(num)

    def resetForms(self):
        '''resets all forms in this servlet... needs to be called either from a servlet's .sleep()
        or in .awake() before any seed() calls.'''
        for form in self._forms:
            if hasattr(form, '_error'):
                form._error = None
            form.reset()


    ## Submission helpers ##
    
    # these methods are part of WebKit and we are stomping them to restore a more familiar
    # .writeHTML() output chain, and to insert form validation
    # this approach is potentially controversial; you could accomplish all this stuff manually
    # in awake() if you wanted to
    
    def preAction(self,actionName): 
        '''Overwrites WebKit method so that a form can be processed by FormKit.'''

        # preAction is called from ._respond() when a button action is happening
        # see WebKit documentation for more information

        # figure out which form (if there are multiple forms) we need to process
        fields = self.request().fields()
        formID = fields.get('__formID__')

        if formID:
            # if there is no formID, we ignore the action (let it pass on through because it
            #   evidently is an action that doesn't pertain to FormKit)

            formID = int(formID)

            # get a handle on the form instance, from the list
            form = self._forms[formID]

            # and trigger its the processing
            # this sends the fields to the form which passes them on to the fields which
            # perform their validation/conversions and report any errors
            form.process( fields )

            # persist feature; if you're using the cookie field persistence feature, this
            # is when it happens
            if form.isSuccessful():             # Note: only happens if the form submission valid
                self.storePersistent()
                # could add other success-condition features here, but most likely you'll want
                # to put them in the .submit() (or other _action_) method in your servlet.

    def postAction(self, actionName):
        '''Overwrites WebKit method so that a form can be re-painted when there are input errors.'''
        # basically, we just want to return control to the normal writeHTML() path
        ## NOTE: by default, WebKit assumes you're going to handle whatever output you want
        ##  to do in the action method itself; the downside to this is that you kinda lose out on the
        ##  writeBody/writeBodyParts/... chain that WebKit provides, which makes it harder to
        ##  maintain your Web application's interface consistency
        self.writeHTML()


    ## other servlet support classes ##

    def storePersistent(self, days=30):
        '''stores any fields marked as persistent into cookies.
        Optionally pass days for the time.time
        REQUIRES self.persistFields to work, but will not crash if it's not there.'''

        # the servlet can override the 30 day default by defining self.persistDays (an int)     
        if hasattr( self, 'persistDays') and self.persistDays is not None:
            days = self.persistDays
        
        if hasattr( self, 'persistFields' ):
            for field in self.persistFields():
                self.setCookie( field, self.form.field(field).value(), days )


    def clearPersistent(self):
        '''clears any fields that are self.persistFields()'''
        if hasattr( self, 'persistFields' ):
            for field in self.persistFields():
                self.clearCookie( field )


    def setCookie(self, key, value, days):
        '''just a helper method to set cookies'''
        cookie = Cookie(key, value)
        t = time.gmtime( time.time() + days*24*60*60 )
        t = time.strftime("%a, %d-%b-%Y %H:%M:%S GMT", t)
        cookie.setExpires(t)
        cookie.setPath('/') # make it work for the whole site
        self.response().addCookie(cookie)


    def clearCookie(self, key):
        '''just a helper method to clear cookies'''
        cookie = Cookie(key, '')
        t = time.gmtime(time.time() - 3600 )    # get some bit into the past
        t = time.strftime("%a, %d-%b-%Y %H:%M:%S GMT", t)
        cookie.setExpires(t)
        cookie.setMaxAge(0)
        cookie.setPath('/') # make it work for the whole site
        self.response().addCookie(cookie)