# w.c.s. - web application for online forms
# Copyright (C) 2005-2019  Entr'ouvert
#
# 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, see <http://www.gnu.org/licenses/>.

import sys
import types

from quixote import get_publisher
from .qommon import _

from wcs.carddata import CardData
from wcs.formdef import FormDef
from wcs.workflows import Workflow

if not hasattr(types, 'ClassType'):
    types.ClassType = type


class CardDef(FormDef):
    _names = 'carddefs'
    data_sql_prefix = 'carddata'
    pickle_module_name = 'carddef'
    xml_root_node = 'carddef'

    confirmation = False

    def data_class(self, mode=None):
        if not 'carddef' in sys.modules:
            sys.modules['carddef'] = sys.modules[__name__]
        if hasattr(sys.modules['carddef'], self.url_name.title()):
            data_class = getattr(sys.modules['carddef'], self.url_name.title())
            # only use existing data class if it has a reference to this actual
            # carddef
            if data_class._formdef is self:
                return data_class
        if (get_publisher().is_using_postgresql() and not mode == 'files') or mode == 'sql':
            from . import sql
            table_name = sql.get_formdef_table_name(self)
            cls = types.ClassType(self.url_name.title(), (sql.SqlCardData,),
                        {'_formdef': self,
                         '_table_name': table_name})
            actions = sql.do_formdef_tables(self)
        else:
            cls = types.ClassType(self.url_name.title(), (CardData,),
                        {'_names': 'card-%s' % self.internal_identifier,
                         '_formdef': self})
            actions = []
        setattr(sys.modules['carddef'], self.url_name.title(), cls)
        setattr(sys.modules['wcs.carddef'], self.url_name.title(), cls)

        if actions:
            for action in actions:
                getattr(cls, action)()

        return cls

    @classmethod
    def get_sql_new_id(cls, id_start):
        from . import sql
        return sql.get_carddef_new_id(id_start=id_start)

    @classmethod
    def wipe(cls):
        super(CardDef, cls).wipe()
        if get_publisher().is_using_postgresql():
            from . import sql
            sql.carddef_wipe()

    @classmethod
    def get_default_workflow(cls):
        from wcs.workflows import EditableWorkflowStatusItem, ChoiceWorkflowStatusItem
        from wcs.wf.remove import RemoveWorkflowStatusItem
        workflow = Workflow(name=_('Default (cards)'))
        workflow.id = '_carddef_default'
        workflow.roles = {
            '_viewer': _('Viewer'),
            '_editor': _('Editor'),
        }
        status = workflow.add_status(_('Recorded'), 'recorded')
        deleted_status = workflow.add_status(_('Deleted'), 'deleted')

        editable = EditableWorkflowStatusItem()
        editable.id = '_editable'
        editable.by = ['_editor']
        editable.label = _('Edit Card')
        editable.status = status.id
        editable.parent = status
        status.items.append(editable)

        action_delete = ChoiceWorkflowStatusItem()
        action_delete.id = '_action_delete'
        action_delete.by = ['_editor']
        action_delete.label = _('Delete Card')
        action_delete.status = deleted_status.id
        action_delete.require_confirmation = True
        action_delete.parent = status
        status.items.append(action_delete)

        remove = RemoveWorkflowStatusItem()
        remove.id = '_remove'
        remove.parent = deleted_status
        deleted_status.items.append(remove)

        return workflow

    def get_url(self, backoffice=False):
        # always return backoffice URL
        base_url = get_publisher().get_backoffice_url() + '/data'
        return '%s/%s/' % (base_url, self.url_name)

    def get_admin_url(self):
        base_url = get_publisher().get_backoffice_url()
        return '%s/cards/%s/' % (base_url, self.id)

    def store(self):
        self.roles = self.backoffice_submission_roles
        return super(CardDef, self).store()
