# -*- coding: iso-8859-15 -*-


# Glasnost
# By: Odile Bénassy <obenassy@entrouvert.com>
#     Romain Chantereau <rchantereau@entrouvert.com>
#     Nicolas Clapiès <nclapies@easter-eggs.org>
#     Pierre-Antoine Dejace <padejace@entrouvert.be>
#     Thierry Dulieu <tdulieu@easter-eggs.com>
#     Florent Monnier <monnier@codelutin.com>
#     Cédric Musso <cmusso@easter-eggs.org>
#     Frédéric Péters <fpeters@entrouvert.be>
#     Benjamin Poussin <poussin@codelutin.com>
#     Emmanuel Raviart <eraviart@entrouvert.com>
#     Sébastien Régnier <regnier@codelutin.com>
#     Emmanuel Saracco <esaracco@easter-eggs.com>
#
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
#     Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
#     Emmanuel Saracco & Théridion
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
#     Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
#     Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
#     Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
#     Régnier, Emmanuel Saracco, Théridion & Vecam
#
# 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.


from __future__ import nested_scopes
    # lambdas are so much fun with nested scopes...


__doc__ = """Glasnost Admin Web Page"""

__version__ = '$Revision$'[11:-2]


import locale

import glasnost.common.faults as faults
import glasnost.common.slots as slots
import glasnost.common.context as context
import glasnost.common.xhtmlgenerator as X

import glasnost.web.kinds as kinds
import glasnost.web.things as things
from glasnost.web.tools import *


class AdminSlot(slots.BaseSlot):
    role = None

    def __init__(self, role, container = None, parent = None):
        slots.BaseSlot.__init__(self, container = container, parent = parent)
        self.role = role

    def getFieldName(self):
        return '_'.join(filter(None, [
            self.getContainerFieldName(),
            self.role]))

    def getFilePathSplitted(self):
        return []

    def getKind(self):
        kind = self.getContainer().admins[self.role].newKind()
        kind.isRequired = 1
        return kind

    def getLabel(self):
        return self.role

    def getLocalValue(self, setIfNone = 0):
        return self.getContainer().admins[self.role]

    def getObject(self):
        return self.getContainer().admins[self.role]

    def getPath(self):
        return self.getContainerPath() + '.' + self.role

    def hasLocalValue(self):
        return self.getContainer().admins.has_key(self.role)


class GlobalAdmin(things.BaseThing):
    admins = None
    webs = None

    def __init__(self):
        things.BaseThing.__init__(self)
        self.admins = {}
        self.webs = {}
        roles = context.getVar('knownRoles')
        for role in roles:
            web = getWebForServerRole(role)
            if web is None:
                continue
            self.webs[role] = web
            if not web.canGetAdmin():
                continue
            admin = web.getAdmin()
            self.admins[role] = admin

    def getEditLayout(self, fields, parentSlot = None):
        layout = X.array()
        for slotName in self.getOrderedSlotNames():
            slot = self.getSlot(slotName, parentSlot = parentSlot)
            admin = slot.getValue()
            web = self.webs[slotName]
            layout += X.h2(_(web.objectsNameCapitalized))
            if web.isAdmin():
                layout += admin.getEditLayout(fields, parentSlot = slot)
            else:
                layout += admin.getViewLayout(fields, parentSlot = slot)
            layout += X.br()
        return layout

    def getOrderedSlotNames(self, parentSlot = None):
        slotNames = self.getSlotNames(parentSlot = parentSlot)
        slotNames.sort(
            lambda slotName1, slotName2:
            locale.strcoll(_(self.webs[slotName1].objectsNameCapitalized),
                           _(self.webs[slotName2].objectsNameCapitalized)))
        return slotNames

    def getSlot(self, role, parentSlot = None):
        if role in ('thingCategory', 'thingName'):
            return slots.Dummy(kinds.String())
        return AdminSlot(role, container = self, parent = parentSlot)

    def getSlotNames(self, parentSlot = None):
        return self.admins.keys()

    def getViewLayout(self, fields, parentSlot = None):
        layout = X.array()
        for slotName in self.getOrderedSlotNames():
            slot = self.getSlot(slotName, parentSlot = parentSlot)
            admin = slot.getValue()
            web = self.webs[slotName]
            layout += X.h2(_(web.objectsNameCapitalized))
            layout += admin.getViewLayout(fields, parentSlot = slot)
            layout += X.br()
        return layout

    def modify(self, parentSlot = None):
        hasWrongVersion = 0
        for slotName in self.getSlotNames(parentSlot = parentSlot):
            slot = self.getSlot(slotName, parentSlot = parentSlot)
            kind = slot.getKind()
            admin = slot.getValue()
            web = self.webs[slotName]
            if web.isAdmin():
                try:
                    web.modifyAdmin(admin)
                except faults.WrongVersion:
                    hasWrongVersion = 1
        if hasWrongVersion:
            raise faults.WrongVersion()

def edit():
    globalAdmin = GlobalAdmin()
    return _editObject(globalAdmin)

def _editObject(globalAdmin):
    context.push(_level = 'edit',
                 defaultDispatcherId = context.getVar('dispatcherId'),
                 layoutMode = 'edit')
    try:
        layout = X.array()
        if context.getVar('error'):
            layout += globalAdmin.getErrorLayout()
        form = X.form(action = X.actionUrl('submit'),
                      enctype = 'multipart/form-data', method = 'post')
        layout += form
        form += globalAdmin.getEditLayout(None)
        form += X.div(_class = 'buttons-bar')(
                    X.buttonInForm('modify', 'modifyButton') )
    finally:
        context.pull(_level = 'edit')
    return writePageLayout(layout, _('Editing Global Settings'))


def index():
    context.push(_level = 'index',
             defaultDispatcherId = context.getVar('dispatcherId'))
    try:
        globalAdmin = GlobalAdmin()
        layout = X.array()
        layout += globalAdmin.getViewLayout(None)
        layout += X.br()
        if context.getVar('userToken', default = ''):
            layout += X.buttonStandalone('edit', X.actionUrl('edit'))
    finally:
        context.pull(_level = 'index')
    return writePageLayout(layout, _('Global Settings'))


def submit(**keywords):
    uri = None
    context.push(_level = 'submit',
                 defaultDispatcherId = context.getVar('dispatcherId'))
    try:
        if keywords is None:
            keywords = {}

        if isButtonSelected('applyButton', keywords):
            context.setVar('again', 1)
            context.SetVar('hideErrors', 1)
        globalAdmin = GlobalAdmin()
        globalAdmin.submitFields(keywords)
        if context.getVar('again'):
            return _editObject(globalAdmin)

        try:
            globalAdmin.modify()
        except faults.WrongVersion:
            context.setVar('again', 1)
            context.setVar('error', 1)
            globalAdmin.setError('version', 1)
            return _editObject(globalAdmin)
        except:
            return accessForbidden()
        return redirect(X.actionUrl())
    finally:
        context.pull(_level = 'submit')

