"""$URL: svn+ssh://svn.mems-exchange.org/repos/trunk/dulcinea/lib/ui/item.py $
$Id: item.py 23235 2003-11-24 21:32:40Z rmasse $

Contains a skeletal class for submitting and updating posted items.
"""

from quixote import get_user
from quixote.errors import AccessError
from quixote.form import Form
from quixote.html import htmltext
from dulcinea import local_ui
from dulcinea.errors import NotLoggedInError

class AbstractItemForm (Form):
    """Skeleton for writing forms that add a posted item

    Subclasses must implement four methods:

    make_new_item() :
      Creates a new item of the right class.
    create_widgets(request) :
      Creates the widgets for the form.
    check_form (request, form_data) :
      Check the form data's validity, and sets self.error accordingly.
    add_item (request) :
      Add a new item, available as self.item, to the appropriate database.
      This method should return a PTL page, which will be shown to the user.
    """

    def __init__ (self, request, item=None):
        Form.__init__(self)
        if item is None:
            item = self.item = self.make_new_item()
            self.new_item = True
        else:
            self.item = item
            self.new_item = False

        self.create_widgets(request)

        if self.new_item:
            self.add_submit_button("Preview", "Preview")
            self.add_submit_button("Submit", "Submit")
            self.add_cancel_button("Cancel", request.get_path(1) + '/')
        else:
            title = self.item.get_title()
            if len(title) > 40:
                title = title[:40] + " ..."
            self.add_submit_button("Update", "Update")
            self.add_cancel_button("Return to %s" % title,
                                   request.get_path(1) + '/')


    def _render_error_notice (self, request):
        if (len(self.error) > 1 or
            len(self.error) == 1 and not self.error.has_key('dummy_field')):
            return Form._render_error_notice(self, request)
        else:
            return ""

    def process (self, request):
        form_data = Form.process(self, request)
        self.check_form(request, form_data)

        # In preview mode and in editing mode, we need to set some
        # error so that the .action() method isn't called and we
        # just return to the form.  This error will never be
        # displayed.
        if (request.form.has_key('Preview') or
            request.form.has_key('Update') ):
            self.error['dummy_field'] = 'dummy message'

        return form_data


    def action (self, request, submit, form_data):
        # Submit the item
        if self.new_item:
            return self.add_item(request)
        else:
            return request.redirect(request.get_path(2) + '/')

    # Subclasses must implement the following methods.
    def make_new_item (self):
        raise RuntimeError('Abstract make_new_item() method called')

    def create_widgets (self, request):
        raise RuntimeError('Abstract create_widgets() method called')

    def check_form (self, request, form_data):
        raise RuntimeError('Abstract check_form() method called')

    def add_item (self, request):
        raise RuntimeError('Abstract add_item() method called')

class ItemDeleteForm(Form):

    def __init__(self, request, item, item_db):
        """(item : Item, item_db : ItemFolder)
        """
        Form.__init__(self)
        self.item = item
        self.item_db = item_db
        self.add_submit_button("Delete", "Delete")
        self.add_cancel_button("Cancel", request.get_path(1) + '/')

    def render(self, request, action_url):
        title = "Delete %s" % self.item.get_title()
        s = htmltext(local_ui.header(title=title))
        s += htmltext('<p>Delete item "%s"?</p>' % self.item.get_title())
        s += Form.render(self, request, action_url)
        s += local_ui.footer(title)
        return s

    def action(self, request, submit, form_data):
        self.item_db.delete_item(self.item)
        return request.redirect(request.get_path(2) + '/')

def delete_item(request, item, item_db, name):
    user = request.session.user
    if user and (user is item.get_user() or user.is_admin()):
        form = ItemDeleteForm(request, item, item_db)
        return form.handle(request)
    else:
        raise AccessError, ("Attempt to delete %s item by non-owner "
                            "or a non-admin user." % name)

def edit_item(request, item, edit_form, name):
    user = get_user()
    if not user:
        raise NotLoggedInError("You must be logged in to edit items.")
    if user is item.get_user() or user.is_admin():
        form = edit_form(request, item)
        return form.handle(request)
    else:
        raise AccessError, ("Attempt to edit %s item by non-owner "
                            "or a non-admin user." % name)
