# -*- 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.


__doc__ = """Glasnost Elections Common Models"""

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


import time

from ObjectsCommon import AdminCommon, ObjectCommon, ObjectsCommonMixin


class AdminElectionsCommon(AdminCommon):
    serverRole = 'elections'

    subjectFormat = 'spip'
    subjectFormat_kind_balloonHelp = N_(
            "The text format to use for the elections. "\
            "[SPIP->syntax-spip] or [reStructredText->syntax-rst] syntax reference.")
    subjectFormat_kind_isRequired = 1
    subjectFormat_kind_label = N_('Text Format')
    subjectFormat_kind_labels = {
        'html': N_('HTML'),
        'spip': N_('SPIP'),
        'rst': N_('reStructured Text'),
        }
    subjectFormat_kind_values = [
        'html',
        'spip',
        'rst',
        ]
    subjectFormat_kindName = 'Choice'
    



class AbstractElectionCommon(ObjectCommon):
    authorsSet = None
    authorsSet_kindName = 'AuthorsSet'

    ballotKind = 'voterChoice'
    ballotKind_kind_balloonHelp = N_('Select the type of the ballots.')
    ballotKind_kind_isRequired = 1
    ballotKind_kind_values = [
        'public',
        'voterChoice',
        'secret',
        ]
    ballotKind_kindName = 'Choice'

    candidateIds = None
    candidateIds_kind_importExport = 'from-server-only'
    candidateIds_kind_itemKind_valueName = 'Id'
    candidateIds_kindName = 'Sequence'

    candidatesSet = None
    candidatesSet_kind_balloonHelp = N_(
            'Choose the candidates for this election.')
    candidatesSet_kind_itemKind_valueName = 'Id'
    candidatesSet_kind_minCount = 1
    candidatesSet_kindName = 'Sequence'

    creationTime = None
    creationTime_kindName = 'CreationTime'

    endTime = None
    endTime_kind_balloonHelp = N_(
            'The time after which it is not possible to vote for '\
            'this election anymore. (You will have to change the '\
            'state of the election to "closed" if you want the '\
            'results to be displayed)')
    endTime_kindName = 'Time'

    isAlwaysRunning = 0
    isAlwaysRunning_kind_balloonHelp = N_(
            'The results of a never ending election are displayed '\
            'right from the start. Otherwise, the state of the '\
            'election must be "closed" for the results to be '\
            'displayed.')
    isAlwaysRunning_kind_isRequired = 1
    isAlwaysRunning_kindName = 'Boolean'

    modificationTime = None
    modificationTime_kindName = 'ModificationTime'

    readersSet = None
    readersSet_kindName = 'ReadersSet'

    serverRole = 'elections'

    state = 'draft'
    state_kind_isRequired = 1
    state_kind_values = [
        'draft',
        'proposed',
        'running',
        'closed',
        ]
    state_kindName = 'Choice'

    subject = None
    class subject_kindClass:
        _kindName = 'String'
        isTranslatable = 1
        isRequired = 1
        label = N_('Subject')
        widget_cols = 75
        widget_colSpan = 2
        widget_preview = 1
        widget_rows = 4
        widgetName = 'TextArea'

        def getTextFormat(self, slot):
            from glasnost.proxy.tools import getProxyForServerRole
            proxy = getProxyForServerRole('elections')
            return proxy.getAdmin().bodyFormat


    title = None
#    title_kind_balloonHelp = N_('Enter the title of this election.')
    title_kind_isRequired = 1
    title_kindName = 'String'

    voteKind = 'VoteRanking'
    voteKind_kind_balloonHelp = N_(
            'You must choose ranking with the Condorcet Method.')
    voteKind_kind_isRequired = 1
    voteKind_kind_values = [
        'VoteApproval',
        'VoteDistribution',
        'VoteRanking',
        'VoteRating',
        ]
    voteKind_kindName = 'Choice'

    votersSet = None
    votersSet_kind_balloonHelp = N_(
            'Choose the persons or groups who will vote for this election.')
    votersSet_kind_minCount = 1
    votersSet_kindName = 'UsersSet'

    voteTokens = None
    voteTokens_kind_importExport = 'from-server-only'
    # A new election has not voteTokens.
    # voteTokens_kind_isRequired = 1
    voteTokens_kind_itemKind_valueName = 'Token'
    voteTokens_kindName = 'Sequence'

    weightingsGradeId = None
    weightingsGradeId_kind_serverRoles = ['grades']
    weightingsGradeId_kindName = 'Id'

    winnerIds = None
    winnerIds_kind_importExport = 'from-server-only'
    winnerIds_kind_itemKind_valueName = 'Id'
    winnerIds_kindName = 'Sequence'

    winnersCount = 1
    winnersCount_kind_balloonHelp = N_(
            'Enter the number of winners this election should have.')
    winnersCount_kind_isRequired = 1
    winnersCount_kindName = 'Integer'

    winnersGroupId = None
    winnersGroupId_kind_serverRoles = ['groups']
    winnersGroupId_kindName = 'Id'

    writersSet = None
    writersSet_kindName = 'WritersSet'

    def canCache(self):
        return 0

    def canCompute(self):
        return self.state == 'closed' \
               or self.state == 'running' and self.isAlwaysRunning \
                   and (self.endTime is None or self.endTime <= time.time())

    def getLabel(self):
        label = self.getTitle()
        if label is None:
            return ''
        return label

    def getOrderedLayoutSlotNames(self, parentSlot = None):
        slotNames = ObjectCommon.getOrderedLayoutSlotNames(
            self, parentSlot = parentSlot)
        slotNames += [
            'title', 'subject', 'creationTime', 'modificationTime', 'endTime',
            'method', 'voteKind', 'isAlwaysRunning', 'ballotKind', 'state',
            'authorsSet', 'writersSet', 'readersSet', 'votersSet',
            'weightingsGradeId', 'candidatesSet', 'winnersCount',
            'winnersGroupId', 'winnerIds']
        return slotNames

    def getTitle(self):
        return self.title

    def getVoterIds(self, virtualServerId = None):
        from glasnost.proxy.GroupsProxy import getSetContainedIds
        return getSetContainedIds(self.votersSet, ['identities'])

    def newVote(self):
        from glasnost.proxy.VotesProxy import votesProxy
        vote = getattr(votesProxy, self.voteKind)()
        if self.ballotKind != 'voter-choice':
            vote.ballotKind = self.ballotKind
        return vote


class ElectionAverageCommon(AbstractElectionCommon):
    ratings = None
    ratings_kind_importExport = 'from-server-only'
    ratings_kind_keyKind_valueName = 'Id'
    ratings_kind_valueKind_valueName = 'Float'
    ratings_kindName = 'Mapping'

    voteKind = 'VoteRating'

    winnersGradeId = None
    winnersGradeId_kind_serverRoles = ['grades']
    winnersGradeId_kindName = 'Id'


class ElectionCondorcetCommon(AbstractElectionCommon):
    pairwiseMatrix = None
    pairwiseMatrix_kind_importExport = 'from-server-only'
    pairwiseMatrix_kindName = 'PairwiseMatrix'

    ratings = None
    ratings_kind_importExport = 'from-server-only'
    ratings_kind_keyKind_valueName = 'Id'
    ratings_kind_valueKind_valueName = 'Rating'
    ratings_kindName = 'Mapping'

    voteKind = 'VoteRanking'


class ElectionsCommonMixin(ObjectsCommonMixin):
    adminClassName = 'AdminElections'
    newObjectNameCapitalized = N_('New Election')
    objectClassName = 'AbstractElection'
    objectName = N_('election')
    objectNameCapitalized = N_('Election')
    objectsName = N_('elections')
    objectsNameCapitalized = N_('Elections')
    serverRole = 'elections'
