from nawah.base_module import BaseModule
from nawah.classes import ATTR, PERM, METHOD
from nawah.config import Config
from nawah.enums import Event


class Group(BaseModule):
	'''`Group` module provides data type and controller for groups in Nawah eco-system.'''

	collection = 'groups'
	attrs = {
		'user': ATTR.ID(desc='`_id` of `User` doc the doc belongs to.'),
		'name': ATTR.LOCALE(desc='Name of the groups as `LOCALE`.'),
		'desc': ATTR.LOCALE(
			desc='Description of the group as `LOCALE`. This can be used for dynamic generated groups that are meant to be exposed to end-users.'
		),
		'privileges': ATTR.KV_DICT(
			desc='Privileges that any user is a member of the group has.',
			key=ATTR.STR(),
			val=ATTR.LIST(list=[ATTR.STR()]),
		),
		'settings': ATTR.KV_DICT(
			desc='`Setting` docs to be created, or required for members users when added to the group.',
			key=ATTR.STR(),
			val=ATTR.ANY(),
		),
		'create_time': ATTR.DATETIME(
			desc='Python `datetime` ISO format of the doc creation.'
		),
	}
	defaults = {
		'desc': {locale: '' for locale in Config.locales},
		'privileges': {},
		'settings': {},
	}
	methods = {
		'read': METHOD(permissions=[PERM(privilege='admin')]),
		'create': METHOD(permissions=[PERM(privilege='admin')]),
		'update': METHOD(
			permissions=[
				PERM(privilege='admin'),
				PERM(
					privilege='update',
					query_mod={'user': '$__user'},
					doc_mod={'privileges': None},
				),
			],
			query_args={'_id': ATTR.ID()},
		),
		'delete': METHOD(
			permissions=[
				PERM(privilege='admin'),
				PERM(privilege='delete', query_mod={'user': '$__user'}),
			],
			query_args={'_id': ATTR.ID()},
		),
	}

	async def pre_update(self, skip_events, env, query, doc, payload):
		# [DOC] Make sure no attrs overwriting would happen
		if 'attrs' in doc.keys():
			results = await self.read(skip_events=[Event.PERM], env=env, query=query)
			if not results.args.count:
				raise self.exception(
					status=400, msg='Group is invalid.', args={'code': 'INVALID_GROUP'}
				)

			if results.args.count > 1:
				raise self.exception(
					status=400,
					msg='Updating group attrs can be done only to individual groups.',
					args={'code': 'MULTI_ATTRS_UPDATE'},
				)

			results.args.docs[0]['attrs'].update(
				{
					attr: doc['attrs'][attr]
					for attr in doc['attrs'].keys()
					if doc['attrs'][attr] != None and doc['attrs'][attr] != ''
				}
			)
			doc['attrs'] = results.args.docs[0]['attrs']
		return (skip_events, env, query, doc, payload)
