"""Basic type with children typically to create process structures."""
from substanced.folder import Folder
from substanced.util import find_service
from substanced.interfaces import IFolder
from zope.interface import implementer
from zope.deprecation import deprecated
from persistent.mapping import PersistentMapping

import adhocracy_core.sheets.name
import adhocracy_core.sheets.pool
import adhocracy_core.sheets.metadata
import adhocracy_core.sheets.title
import adhocracy_core.sheets.workflow
from adhocracy_core.interfaces import IPool
from adhocracy_core.resources import add_resource_type_to_registry
from adhocracy_core.resources import resource_meta
from adhocracy_core.resources.base import Base
from adhocracy_core.resources.base import Length
from adhocracy_core.utils import now


class IBasicPool(IPool):

    """Basic Pool."""


deprecated('IBasicPool', 'Backward compatible code, use organisation or pool')


@implementer(IPool, IFolder)
class Pool(Base, Folder):

    """An Auto-Naming Folder.

    Custom names are allowed and coexists with the autogenerated names.

    The next_name method sequentially increments the last name:
    ``0000001``, then ``0000002``, and so on.
    """

    #  The pool needs to provide IFolder to make substance.util.find_service
    # work

    _autoname_length = 7

    def __init__(self, data=None, family=None):
        """Counter that should increment if descendants are changed."""
        Folder.__init__(self, data=data, family=family)
        Base.__init__(self)
        self.__changed_descendants_counter__ = Length()
        self._autoname_lasts = PersistentMapping()

    def next_name(self, subobject, prefix='') -> str:
        """Generate name to add subobject to the folder.

        This method does:

            - increment the last generated name associated to the prefix.
            - zero-filling the left hand side of the result with 7 zeros.
            - add prefix to the left hand side if any

        If the generated Name exists add timestamp to the right side.

        """
        number = self._get_next_number(prefix)
        name = prefix + self._zfill(number)
        if name in self.data:
            timestamp = now().isoformat()
            name += '_' + timestamp
        return name

    def add_next(self, subobject, prefix=''):
        """Add a subobject and name it automatically.

        Use the name returned by this folder's ``next_name`` method.

        """
        name = self.next_name(subobject, prefix=prefix)
        return self.add(name, subobject, send_events=False)

    def _zfill(self, name):
        return str(int(name)).zfill(self._autoname_length)

    def _get_next_number(self, prefix):
        if prefix in self._autoname_lasts:
            number = self._autoname_lasts[prefix]
        else:
            number = 0
            self._autoname_lasts[prefix] = number
        self._autoname_lasts[prefix] += 1
        return number

    def find_service(self, service_name, *sub_service_names):
        """Return  the :term:`service` for the given context."""
        return find_service(self, service_name, *sub_service_names)


pool_meta = resource_meta._replace(
    iresource=IPool,
    content_class=Pool,
    permission_create='create_pool',
    is_implicit_addable=False,
    basic_sheets=(adhocracy_core.sheets.name.IName,
                  adhocracy_core.sheets.title.ITitle,
                  adhocracy_core.sheets.pool.IPool,
                  adhocracy_core.sheets.metadata.IMetadata,
                  adhocracy_core.sheets.workflow.IWorkflowAssignment,
                  ),
    extended_sheets=(),
    element_types=(IPool,),
)


basicpool_meta = pool_meta._replace(
    iresource=IBasicPool,
    is_implicit_addable=True,
)


def includeme(config):
    """Add resource type to registry."""
    add_resource_type_to_registry(basicpool_meta, config)
    add_resource_type_to_registry(pool_meta, config)
